static void vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1) { char *p; int i; for (i = 0; i < ind; i++) VSB_cat(d, " "); p = VSB_data(e1->vsb); while (*p != '\0') { if (*p == '\n') { VSB_putc(d, '\n'); if (p[1] != '\0') { for (i = 0; i < ind; i++) VSB_cat(d, " "); } p++; continue; } if (*p != '\v') { VSB_putc(d, *p); p++; continue; } p++; switch(*p) { case '+': ind += 2; break; case '-': ind -= 2; break; default: assert(__LINE__ == 0); } p++; } }
void VRT_synth_page(const struct sess *sp, unsigned flags, const char *str, ...) { va_list ap; const char *p; struct vsb *vsb; (void)flags; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp->wrk->obj, OBJECT_MAGIC); vsb = SMS_Makesynth(sp->wrk->obj); AN(vsb); VSB_cat(vsb, str); va_start(ap, str); p = va_arg(ap, const char *); while (p != vrt_magic_string_end) { if (p == NULL) p = "(null)"; VSB_cat(vsb, p); p = va_arg(ap, const char *); } va_end(ap); SMS_Finish(sp->wrk->obj); http_Unset(sp->wrk->obj->http, H_Content_Length); http_PrintfHeader(sp->wrk, sp->vsl_id, sp->wrk->obj->http, "Content-Length: %zd", sp->wrk->obj->len); }
static void vbackends_show_json(struct vsb *json, char *raw) { char *tokens = NULL, *ptr = NULL; char tmp[1000]; int raw_len = 0; int cont = 0; int sum = 0; raw_len = strlen(raw); tokens = strtok(raw, "\n"); sum = sum + strlen(tokens); VSB_cat(json, "{\n \"backends\" : [\n"); while(tokens != NULL){ strcpy(tmp, (tokens)); tokens = strtok(NULL, "\n"); sum = sum + strlen(tmp); if(cont > 0){ ptr = format_line(tmp); VSB_cat(json, ptr); if(sum < raw_len) VSB_cat(json, ",\n"); free(ptr); } cont++; } VSB_cat(json, "\n]\n}\n"); }
static struct expr * vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1, struct expr *e2) { struct expr *e; int nl = 1; e = vcc_new_expr(); while (*p != '\0') { if (*p == '\n') { if (!nl) VSB_putc(e->vsb, *p); nl = 1; p++; continue; } nl = 0; if (*p != '\v') { VSB_putc(e->vsb, *p); p++; continue; } assert(*p == '\v'); p++; switch(*p) { case '+': VSB_cat(e->vsb, "\v+"); break; case '-': VSB_cat(e->vsb, "\v-"); break; case '1': case '2': if (*p == '1') VSB_cat(e->vsb, VSB_data(e1->vsb)); else { AN(e2); VSB_cat(e->vsb, VSB_data(e2->vsb)); } break; default: assert(__LINE__ == 0); } p++; } AZ(VSB_finish(e->vsb)); if (e1 != NULL) e->t1 = e1->t1; else if (e2 != NULL) e->t1 = e2->t1; if (e2 != NULL) e->t2 = e2->t1; else if (e1 != NULL) e->t1 = e1->t1; if ((e1 == NULL || e1->constant) && (e2 == NULL || e2->constant)) e->constant = 1; vcc_delete_expr(e1); vcc_delete_expr(e2); e->fmt = fmt; return (e); }
/* * Quote a string */ void VSB_quote(struct vsb *s, const char *p, int len, int how) { const char *q; int quote = 0; (void)how; /* For future enhancements */ if (len == -1) len = strlen(p); for (q = p; q < p + len; q++) { if (!isgraph(*q) || *q == '"' || *q == '\\') { quote++; break; } } if (!quote) { (void)VSB_bcat(s, p, len); return; } (void)VSB_putc(s, '"'); for (q = p; q < p + len; q++) { switch (*q) { case ' ': (void)VSB_putc(s, *q); break; case '\\': case '"': (void)VSB_putc(s, '\\'); (void)VSB_putc(s, *q); break; case '\n': if (how & VSB_QUOTE_NONL) (void)VSB_cat(s, "\n"); else (void)VSB_cat(s, "\\n"); break; case '\r': (void)VSB_cat(s, "\\r"); break; case '\t': (void)VSB_cat(s, "\\t"); break; default: if (isgraph(*q)) (void)VSB_putc(s, *q); else (void)VSB_printf(s, "\\%o", *q & 0xff); break; } } (void)VSB_putc(s, '"'); }
static int vbp_write_proxy_v1(struct vbp_target *vt, int *sock) { char buf[105]; /* maximum size for a TCP6 PROXY line with null char */ char addr[VTCP_ADDRBUFSIZE]; char port[VTCP_PORTBUFSIZE]; struct sockaddr_storage ss; struct vsb vsb; socklen_t l; VTCP_myname(*sock, addr, sizeof addr, port, sizeof port); AN(VSB_new(&vsb, buf, sizeof buf, VSB_FIXEDLEN)); l = sizeof ss; AZ(getsockname(*sock, (void *)&ss, &l)); if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) { VSB_printf(&vsb, "PROXY %s %s %s %s %s\r\n", ss.ss_family == AF_INET ? "TCP4" : "TCP6", addr, addr, port, port); } else VSB_cat(&vsb, "PROXY UNKNOWN\r\n"); AZ(VSB_finish(&vsb)); return (vbp_write(vt, sock, VSB_data(&vsb), VSB_len(&vsb))); }
static void vbp_build_req(struct vbp_target *vt, const struct vrt_backend_probe *vbp, const struct backend *be) { struct vsb *vsb; vsb = VSB_new_auto(); AN(vsb); VSB_clear(vsb); if (vbp->request != NULL) { VSB_cat(vsb, vbp->request); } else { VSB_printf(vsb, "GET %s HTTP/1.1\r\n", vbp->url != NULL ? vbp->url : "/"); if (be->hosthdr != NULL) VSB_printf(vsb, "Host: %s\r\n", be->hosthdr); VSB_printf(vsb, "Connection: close\r\n"); VSB_printf(vsb, "\r\n"); } AZ(VSB_finish(vsb)); vt->req = strdup(VSB_data(vsb)); AN(vt->req); vt->req_len = VSB_len(vsb); VSB_destroy(&vsb); }
static unsigned mgt_vcc_compile(struct vcc_priv *vp, struct vsb *sb, int C_flag) { char *csrc; unsigned subs; if (mgt_vcc_touchfile(vp->srcfile, sb)) return (2); if (mgt_vcc_touchfile(vp->libfile, sb)) return (2); subs = VSUB_run(sb, run_vcc, vp, "VCC-compiler", -1); if (subs) return (subs); if (C_flag) { csrc = VFIL_readfile(NULL, vp->srcfile, NULL); AN(csrc); VSB_cat(sb, csrc); free(csrc); } subs = VSUB_run(sb, run_cc, vp, "C-compiler", 10); if (subs) return (subs); subs = VSUB_run(sb, run_dlopen, vp, "dlopen", 10); return (subs); }
void VRT_synth_page(const struct vrt_ctx *ctx, unsigned flags, const char *str, ...) { va_list ap; const char *p; struct vsb *vsb; (void)flags; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); CHECK_OBJ_NOTNULL(ctx->req->obj, OBJECT_MAGIC); vsb = SMS_Makesynth(ctx->req->obj); AN(vsb); va_start(ap, str); p = str; while (p != vrt_magic_string_end) { if (p == NULL) p = "(null)"; VSB_cat(vsb, p); p = va_arg(ap, const char *); } va_end(ap); SMS_Finish(ctx->req->obj); http_Unset(ctx->req->obj->http, H_Content_Length); }
void VRT_synth_page(VRT_CTX, const char *str, ...) { va_list ap; const char *p; struct vsb *vsb; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); if (ctx->method == VCL_MET_BACKEND_ERROR) { CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC); vsb = ctx->bo->synth_body; } else { CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); vsb = ctx->req->synth_body; } AN(vsb); va_start(ap, str); p = str; while (p != vrt_magic_string_end) { if (p == NULL) p = "(null)"; VSB_cat(vsb, p); p = va_arg(ap, const char *); } va_end(ap); }
run_cc(void *priv) { struct vcc_priv *vp; struct vsb *sb; int pct; char *p; VJ_subproc(JAIL_SUBPROC_CC); CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC); AZ(chdir(vp->dir)); sb = VSB_new_auto(); AN(sb); for (p = mgt_cc_cmd, pct = 0; *p; ++p) { if (pct) { switch (*p) { case 's': VSB_cat(sb, VGC_SRC); break; case 'o': VSB_cat(sb, VGC_LIB); break; case '%': VSB_putc(sb, '%'); break; default: VSB_putc(sb, '%'); VSB_putc(sb, *p); break; } pct = 0; } else if (*p == '%') { pct = 1; } else { VSB_putc(sb, *p); } } if (pct) VSB_putc(sb, '%'); AZ(VSB_finish(sb)); (void)umask(027); (void)execl("/bin/sh", "/bin/sh", "-c", VSB_data(sb), (char*)0); VSB_destroy(&sb); // For flexelint }
/* * Copy a string into an vsb. */ int VSB_cpy(struct vsb *s, const char *str) { assert_VSB_integrity(s); assert_VSB_state(s, 0); VSB_clear(s); return (VSB_cat(s, str)); }
static struct expr * vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1, struct expr *e2) { struct expr *e; int nl = 1; AN(e1); e = vcc_new_expr(); while (*p != '\0') { if (*p != '\v') { if (*p != '\n' || !nl) VSB_putc(e->vsb, *p); nl = (*p == '\n'); p++; continue; } assert(*p == '\v'); switch(*++p) { case '+': VSB_cat(e->vsb, "\v+"); break; case '-': VSB_cat(e->vsb, "\v-"); break; case '1': VSB_cat(e->vsb, VSB_data(e1->vsb)); break; case '2': AN(e2); VSB_cat(e->vsb, VSB_data(e2->vsb)); break; default: WRONG("Illegal edit in VCC expression"); } p++; } AZ(VSB_finish(e->vsb)); e->t1 = e1->t1; e->t2 = e1->t2; if (e2 != NULL) e->t2 = e2->t2; vcc_delete_expr(e1); vcc_delete_expr(e2); e->fmt = fmt; return (e); }
const struct var * vcc_FindVar(struct vcc *tl, const struct token *t, int wr_access, const char *use) { const struct var *v; const struct symbol *sym; AN(tl->vars); sym = VCC_FindSymbol(tl, t, SYM_VAR); if (sym != NULL) { v = sym->var; AN(v); if (wr_access && v->w_methods == 0) { VSB_printf(tl->sb, "Variable "); vcc_ErrToken(tl, t); VSB_printf(tl->sb, " is read only."); VSB_cat(tl->sb, "\nAt: "); vcc_ErrWhere(tl, t); return (NULL); } else if (wr_access) { vcc_AddUses(tl, t, v->w_methods, use); } else if (v->r_methods == 0) { VSB_printf(tl->sb, "Variable "); vcc_ErrToken(tl, t); VSB_printf(tl->sb, " is write only."); VSB_cat(tl->sb, "\nAt: "); vcc_ErrWhere(tl, t); return (NULL); } else { vcc_AddUses(tl, t, v->r_methods, use); } assert(v->fmt != HEADER); return (v); } VSB_printf(tl->sb, "Unknown variable "); vcc_ErrToken(tl, t); VSB_cat(tl->sb, "\nAt: "); vcc_ErrWhere(tl, t); return (NULL); }
static void ban_parse_http(const struct ban_proto *bp, const char *a1) { int l; l = strlen(a1) + 1; assert(l <= 127); VSB_putc(bp->vsb, (char)l); VSB_cat(bp->vsb, a1); VSB_putc(bp->vsb, ':'); VSB_putc(bp->vsb, '\0'); }
struct vsb * macro_expand(struct vtclog *vl, const char *text) { struct vsb *vsb; const char *p, *q; char *m; vsb = VSB_new_auto(); AN(vsb); while (*text != '\0') { p = strstr(text, "${"); if (p == NULL) { VSB_cat(vsb, text); break; } VSB_bcat(vsb, text, p - text); q = strchr(p, '}'); if (q == NULL) { VSB_cat(vsb, text); break; } assert(p[0] == '$'); assert(p[1] == '{'); assert(q[0] == '}'); p += 2; m = macro_get(p, q); if (m == NULL) { VSB_delete(vsb); vtc_log(vl, 0, "Macro ${%.*s} not found", (int)(q - p), p); return (NULL); } VSB_printf(vsb, "%s", m); free(m); text = q + 1; } AZ(VSB_finish(vsb)); return (vsb); }
void vcc_Eval_Func(struct vcc *tl, const char *cfunc, const char *extra, const char *name, const char *args) { struct expr *e = NULL; struct token *t1; t1 = tl->t; vcc_func(tl, &e, cfunc, extra, name, args); if (!tl->err) { vcc_expr_fmt(tl->fb, tl->indent, e); VSB_cat(tl->fb, ";\n"); } else if (t1 != tl->t) { vcc_ErrWhere2(tl, t1, tl->t); } vcc_delete_expr(e); }
void vcc_Expr_Call(struct vcc *tl, const struct symbol *sym) { struct expr *e; struct token *t1; t1 = tl->t; e = NULL; vcc_Eval_Func(tl, &e, sym); if (!tl->err) { vcc_expr_fmt(tl->fb, tl->indent, e); VSB_cat(tl->fb, ";\n"); } else if (t1 != tl->t) { vcc_ErrWhere2(tl, t1, tl->t); } vcc_delete_expr(e); }
void VRT_synth_page(VRT_CTX, const char *str, ...) { va_list ap; const char *p; struct vsb *vsb; CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC); va_start(ap, str); p = str; while (p != vrt_magic_string_end) { if (p == NULL) p = "(null)"; VSB_cat(vsb, p); p = va_arg(ap, const char *); } va_end(ap); }
static void vbp_build_req(struct vbp_target *vt, const char *hosthdr) { struct vsb *vsb; vsb = VSB_new_auto(); AN(vsb); VSB_clear(vsb); if(vt->probe.request != NULL) { VSB_cat(vsb, vt->probe.request); } else { VSB_printf(vsb, "GET %s HTTP/1.1\r\n", vt->probe.url != NULL ? vt->probe.url : "/"); if (hosthdr != NULL) VSB_printf(vsb, "Host: %s\r\n", hosthdr); VSB_printf(vsb, "Connection: close\r\n"); VSB_printf(vsb, "\r\n"); } AZ(VSB_finish(vsb)); vt->req = strdup(VSB_data(vsb)); AN(vt->req); vt->req_len = VSB_len(vsb); VSB_delete(vsb); }
static void vcc_ParseProbeSpec(struct vcc *tl, const struct symbol *sym, char **name) { struct fld_spec *fs; struct token *t_field; struct token *t_did = NULL, *t_window = NULL, *t_threshold = NULL; struct token *t_initial = NULL; struct vsb *vsb; char *retval; unsigned window, threshold, initial, status; double t; fs = vcc_FldSpec(tl, "?url", "?request", "?expected_response", "?timeout", "?interval", "?window", "?threshold", "?initial", NULL); SkipToken(tl, '{'); vsb = VSB_new_auto(); AN(vsb); if (sym != NULL) VSB_cat(vsb, sym->rname); else VSB_printf(vsb, "vgc_probe__%d", tl->nprobe++); AZ(VSB_finish(vsb)); retval = TlDup(tl, VSB_data(vsb)); AN(retval); VSB_destroy(&vsb); if (name != NULL) *name = retval; window = 0; threshold = 0; initial = 0; status = 0; Fh(tl, 0, "static const struct vrt_backend_probe %s[] = {{\n", retval); Fh(tl, 0, "\t.magic = VRT_BACKEND_PROBE_MAGIC,\n"); while (tl->t->tok != '}') { vcc_IsField(tl, &t_field, fs); ERRCHK(tl); if (vcc_IdIs(t_field, "url")) { vcc_Redef(tl, "Probe request", &t_did, t_field); ERRCHK(tl); ExpectErr(tl, CSTR); Fh(tl, 0, "\t.url = "); EncToken(tl->fh, tl->t); Fh(tl, 0, ",\n"); vcc_NextToken(tl); } else if (vcc_IdIs(t_field, "request")) { vcc_Redef(tl, "Probe request", &t_did, t_field); ERRCHK(tl); ExpectErr(tl, CSTR); Fh(tl, 0, "\t.request =\n"); while (tl->t->tok == CSTR) { Fh(tl, 0, "\t\t"); EncToken(tl->fh, tl->t); Fh(tl, 0, " \"\\r\\n\"\n"); vcc_NextToken(tl); } Fh(tl, 0, "\t\t\"\\r\\n\",\n"); } else if (vcc_IdIs(t_field, "timeout")) { Fh(tl, 0, "\t.timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fh(tl, 0, "%g,\n", t); } else if (vcc_IdIs(t_field, "interval")) { Fh(tl, 0, "\t.interval = "); vcc_Duration(tl, &t); ERRCHK(tl); Fh(tl, 0, "%g,\n", t); } else if (vcc_IdIs(t_field, "window")) { t_window = tl->t; window = vcc_UintVal(tl); ERRCHK(tl); } else if (vcc_IdIs(t_field, "initial")) { t_initial = tl->t; initial = vcc_UintVal(tl); ERRCHK(tl); } else if (vcc_IdIs(t_field, "expected_response")) { status = vcc_UintVal(tl); if (status < 100 || status > 999) { VSB_printf(tl->sb, "Must specify .expected_response with " "exactly three digits " "(100 <= x <= 999)\n"); vcc_ErrWhere(tl, tl->t); return; } ERRCHK(tl); } else if (vcc_IdIs(t_field, "threshold")) { t_threshold = tl->t; threshold = vcc_UintVal(tl); ERRCHK(tl); } else { vcc_ErrToken(tl, t_field); vcc_ErrWhere(tl, t_field); ErrInternal(tl); return; } SkipToken(tl, ';'); } if (t_threshold != NULL || t_window != NULL) { if (t_threshold == NULL && t_window != NULL) { VSB_printf(tl->sb, "Must specify .threshold with .window\n"); vcc_ErrWhere(tl, t_window); return; } else if (t_threshold != NULL && t_window == NULL) { if (threshold > 64) { VSB_printf(tl->sb, "Threshold must be 64 or less.\n"); vcc_ErrWhere(tl, t_threshold); return; } window = threshold + 1; } else if (window > 64) { AN(t_window); VSB_printf(tl->sb, "Window must be 64 or less.\n"); vcc_ErrWhere(tl, t_window); return; } if (threshold > window ) { VSB_printf(tl->sb, "Threshold can not be greater than window.\n"); AN(t_threshold); vcc_ErrWhere(tl, t_threshold); AN(t_window); vcc_ErrWhere(tl, t_window); } Fh(tl, 0, "\t.window = %u,\n", window); Fh(tl, 0, "\t.threshold = %u,\n", threshold); } if (t_initial != NULL) Fh(tl, 0, "\t.initial = %u,\n", initial); else Fh(tl, 0, "\t.initial = ~0U,\n"); if (status > 0) Fh(tl, 0, "\t.exp_status = %u,\n", status); Fh(tl, 0, "}};\n"); SkipToken(tl, '}'); }
void vdir_list(VRT_CTX, struct vdir *vd, struct vsb *vsb, int pflag, int jflag, int weight) { VCL_BACKEND be; VCL_BOOL h; unsigned u, nh; double w; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); if (pflag) { if (jflag) { VSB_cat(vsb, "{\n"); VSB_indent(vsb, 2); if (weight) VSB_printf(vsb, "\"total_weight\": %f,\n", vd->total_weight); VSB_cat(vsb, "\"backends\": {\n"); VSB_indent(vsb, 2); } else { VSB_cat(vsb, "\n\n\tBackend\tWeight\tHealth\n"); } } vdir_rdlock(vd); vdir_update_health(ctx, vd); for (u = 0; pflag && u < vd->n_backend; u++) { be = vd->backend[u]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); h = vbit_test(vd->healthy, u); w = h ? vd->weight[u] : 0.0; if (jflag) { if (u) VSB_cat(vsb, ",\n"); VSB_printf(vsb, "\"%s\": {\n", be->vcl_name); VSB_indent(vsb, 2); if (weight) VSB_printf(vsb, "\"weight\": %f,\n", w); if (h) VSB_cat(vsb, "\"health\": \"healthy\"\n"); else VSB_cat(vsb, "\"health\": \"sick\"\n"); VSB_indent(vsb, -2); VSB_cat(vsb, "}"); } else { VSB_cat(vsb, "\t"); VSB_cat(vsb, be->vcl_name); if (weight) VSB_printf(vsb, "\t%6.2f%%\t", 100 * w / vd->total_weight); else VSB_cat(vsb, "\t-\t"); VSB_cat(vsb, h ? "healthy" : "sick"); VSB_cat(vsb, "\n"); } } nh = vd->n_healthy; u = vd->n_backend; vdir_unlock(vd); if (jflag && (pflag)) { VSB_cat(vsb, "\n"); VSB_indent(vsb, -2); VSB_cat(vsb, "}\n"); VSB_indent(vsb, -2); VSB_cat(vsb, "},\n"); } if (pflag) return; if (jflag) VSB_printf(vsb, "[%u, %u, \"%s\"]", nh, u, nh ? "healthy" : "sick"); else VSB_printf(vsb, "%u/%u\t%s", nh, u, nh ? "healthy" : "sick"); }
void vcl_output_lang_h(struct vsb *sb) { /* ../include/vcl.h */ VSB_cat(sb, "/*\n * NB: This file is machine generated, DO " "NOT EDIT!\n *\n * Edit and run generate.py instead\n" " */\n\nstruct sess;\nstruct cli;\n\ntypedef int vcl_init_f(struc" "t cli *);\ntypedef void vcl_fini_f(struct cli *);\n" "typedef int vcl_func_f(struct sess *sp);\n\n/* VCL Methods " "*/\n#define VCL_MET_RECV\t\t(1U << 0)\n#define VCL_MET_PIPE\t" "\t(1U << 1)\n#define VCL_MET_PASS\t\t(1U << 2)\n#define VCL_MET_" "HASH\t\t(1U << 3)\n#define VCL_MET_MISS\t\t(1U << 4)\n" "#define VCL_MET_HIT\t\t(1U << 5)\n#define VCL_MET_FETCH\t\t" "(1U << 6)\n#define VCL_MET_DELIVER\t\t(1U << 7)\n" "#define VCL_MET_ERROR\t\t(1U << 8)\n#define VCL_MET_INIT\t\t" "(1U << 9)\n#define VCL_MET_FINI\t\t(1U << 10)\n\n" "#define VCL_MET_MAX\t\t11\n\n#define VCL_MET_MASK\t\t0x7ff\n" "\n/* VCL Returns */\n#define VCL_RET_DELIVER\t\t0\n" "#define VCL_RET_ERROR\t\t1\n#define VCL_RET_FETCH\t\t2\n" "#define VCL_RET_HASH\t\t3\n#define VCL_RET_HIT_FOR_PASS\t\t" "4\n#define VCL_RET_LOOKUP\t\t5\n#define VCL_RET_OK\t\t6\n" "#define VCL_RET_PASS\t\t7\n#define VCL_RET_PIPE\t\t8\n" "#define VCL_RET_RESTART\t\t9\n\n#define VCL_RET_MAX\t\t10\n" "\nstruct VCL_conf {\n\tunsigned\tmagic;\n#define VCL_CONF_MAGIC\t" "0x7406c509\t/* from /dev/random */\n\n\tstruct director\t**direc" "tor;\n\tunsigned\tndirector;\n\tstruct vrt_ref\t*ref;\n" "\tunsigned\tnref;\n\tunsigned\tbusy;\n\tunsigned\tdiscard;\n" "\n\tunsigned\tnsrc;\n\tconst char\t**srcname;\n\tconst char\t" "**srcbody;\n\n\tvcl_init_f\t*init_vcl;\n\tvcl_fini_f\t*fini_vcl;" "\n\tvcl_func_f\t*recv_func;\n\tvcl_func_f\t*pipe_func;\n" "\tvcl_func_f\t*pass_func;\n\tvcl_func_f\t*hash_func;\n" "\tvcl_func_f\t*miss_func;\n\tvcl_func_f\t*hit_func;\n" "\tvcl_func_f\t*fetch_func;\n\tvcl_func_f\t*deliver_func;\n" "\tvcl_func_f\t*error_func;\n\tvcl_func_f\t*init_func;\n" "\tvcl_func_f\t*fini_func;\n\n};\n" ); /* ../include/vrt.h */ VSB_cat(sb, "/*-\n * Copyright (c) 2006 Verdens Gang AS\n" " * Copyright (c) 2006-2010 Varnish Software AS\n * All rights " "reserved.\n *\n * Author: Poul-Henning Kamp <*****@*****.**>" "\n *\n * Redistribution and use in source and binary forms, " "with or without\n * modification, are permitted provided that " "the following conditions\n * are met:\n * 1. Redistributions " "of source code must retain the above copyright\n * notice, " "this list of conditions and the following disclaimer.\n" " * 2. Redistributions in binary form must reproduce the above " "copyright\n * notice, this list of conditions and the followi" "ng disclaimer in the\n * documentation and/or other materials" " provided with the distribution.\n *\n * THIS SOFTWARE IS " "PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n" " * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED" " TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS " "FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT " "SHALL AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, " "INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n" " * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF " "SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS;" " OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY " "OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR " "TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n" " * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE " "POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * Runtime support for " "compiled VCL programs.\n *\n * XXX: When this file is changed, " "lib/libvcl/generate.py *MUST* be rerun.\n */\n\nstruct sess;\n" "struct vsb;\nstruct cli;\nstruct director;\nstruct VCL_conf;\n" "struct sockaddr_storage;\n\n/*\n * A backend probe specification" "\n */\n\nextern const void * const vrt_magic_string_end;\n" "\nstruct vrt_backend_probe {\n\tconst char\t*url;\n" "\tconst char\t*request;\n\tdouble\t\ttimeout;\n\tdouble\t\t" "interval;\n\tunsigned\texp_status;\n\tunsigned\twindow;\n" "\tunsigned\tthreshold;\n\tunsigned\tinitial;\n};\n" "\n/*\n * A backend is a host+port somewhere on the network\n" " */\nstruct vrt_backend {\n\tconst char\t\t\t*vcl_name;\n" "\tconst char\t\t\t*ipv4_addr;\n\tconst char\t\t\t*ipv6_addr;\n" "\tconst char\t\t\t*port;\n\n\tconst unsigned char\t\t*ipv4_socka" "ddr;\n\tconst unsigned char\t\t*ipv6_sockaddr;\n\n" "\tconst char\t\t\t*hosthdr;\n\n\tdouble\t\t\t\tconnect_timeout;\n" "\tdouble\t\t\t\tfirst_byte_timeout;\n\tdouble\t\t\t\tbetween_byt" "es_timeout;\n\tunsigned\t\t\tmax_connections;\n\tunsigned\t" "\t\tsaintmode_threshold;\n\tconst struct vrt_backend_probe\t" "*probe;\n};\n\n/*\n * A director with an unpredictable reply\n" " */\n\nstruct vrt_dir_random_entry {\n\tint\t\t\t\t\thost;\n" "\tdouble\t\t\t\t\tweight;\n};\n\nstruct vrt_dir_random {\n" "\tconst char\t\t\t\t*name;\n\tunsigned\t\t\t\tretries;\n" "\tunsigned\t\t\t\tnmember;\n\tconst struct vrt_dir_random_entry\t" "*members;\n};\n\n/*\n * A director with round robin selection\n" " */\n\nstruct vrt_dir_round_robin_entry {\n\tint\t\t\t\t\thost;\n" "};\n\nstruct vrt_dir_round_robin {\n\tconst char\t\t\t\t*name;\n" "\tunsigned\t\t\t\tnmember;\n\tconst struct vrt_dir_round_robin_e" "ntry\t*members;\n};\n\n/*\n * A director with dns-based selectio" "n\n */\n\nstruct vrt_dir_dns_entry {\n\tint\t\t\t\t\thost;\n" "};\n\nstruct vrt_dir_dns {\n\tconst char\t\t\t\t*name;\n" "\tconst char\t\t\t\t*suffix;\n\tconst double\t\t\t\tttl;\n" "\tunsigned\t\t\t\tnmember;\n\tconst struct vrt_dir_dns_entry\t" "\t*members;\n};\n\n/*\n * other stuff.\n * XXX: document when " "bored\n */\n\nstruct vrt_ref {\n\tunsigned\tsource;\n" "\tunsigned\toffset;\n\tunsigned\tline;\n\tunsigned\tpos;\n" "\tunsigned\tcount;\n\tconst char\t*token;\n};\n\n" "/* ACL related */\n#define VRT_ACL_MAXADDR\t\t16\t/* max(IPv4, " "IPv6) */\n\nvoid VRT_acl_log(const struct sess *, const char " "*msg);\n\n/* Regexp related */\nvoid VRT_re_init(void **, " "const char *);\nvoid VRT_re_fini(void *);\nint VRT_re_match(cons" "t struct sess *sp, const char *, void *re);\nconst char *VRT_reg" "sub(const struct sess *sp, int all, const char *,\n" " void *, const char *);\n\nvoid VRT_panic(const struct " "sess *sp, const char *, ...);\nvoid VRT_ban(struct sess *sp, " "char *, ...);\nvoid VRT_ban_string(struct sess *sp, const " "char *);\nvoid VRT_purge(const struct sess *sp, double ttl, " "double grace);\n\nvoid VRT_count(const struct sess *, unsigned);" "\nint VRT_rewrite(const char *, const char *);\nvoid VRT_error(s" "truct sess *, unsigned, const char *);\nint VRT_switch_config(co" "nst char *);\n\nenum gethdr_e { HDR_REQ, HDR_RESP, HDR_OBJ, " "HDR_BEREQ, HDR_BERESP };\nchar *VRT_GetHdr(const struct sess " "*, enum gethdr_e where, const char *);\nvoid VRT_SetHdr(const " "struct sess *, enum gethdr_e where, const char *,\n" " const char *, ...);\nvoid VRT_handling(struct sess *sp, " "unsigned hand);\n\nvoid VRT_hashdata(const struct sess *sp, " "const char *str, ...);\n\n/* Simple stuff */\nint VRT_strcmp(con" "st char *s1, const char *s2);\nvoid VRT_memmove(void *dst, " "const void *src, unsigned len);\n\nvoid VRT_ESI(const struct " "sess *sp);\nvoid VRT_Rollback(struct sess *sp);\n" "\n/* Synthetic pages */\nvoid VRT_synth_page(const struct " "sess *sp, unsigned flags, const char *, ...);\n\n" "/* Backend related */\nvoid VRT_init_dir(struct cli *, struct " "director **, const char *name,\n int idx, const void *priv);\n" "void VRT_fini_dir(struct cli *, struct director *);\n" "\n/* VMOD/Modules related */\nint VRT_Vmod_Init(void **hdl, " "void *ptr, int len, const char *nm,\n const char *path, " "struct cli *cli);\nvoid VRT_Vmod_Fini(void **hdl);\n" "\nstruct vmod_priv;\ntypedef void vmod_priv_free_f(void *);\n" "struct vmod_priv {\n\tvoid\t\t\t*priv;\n\tvmod_priv_free_f\t" "*free;\n};\n\ntypedef int vmod_init_f(struct vmod_priv *, " " const struct VCL_conf *);\n\nstatic inline void\n" "vmod_priv_fini(const struct vmod_priv *p)\n{\n\n\tif (p->priv " "!= (void*)0 && p->free != (void*)0)\n\t\tp->free(p->priv);\n" "}\n\n/* Stevedore related functions */\nint VRT_Stv(const " "char *nm);\n\n/* Convert things to string */\n\nchar *VRT_IP_str" "ing(const struct sess *sp, const struct sockaddr_storage *sa);\n" "char *VRT_int_string(const struct sess *sp, int);\n" "char *VRT_double_string(const struct sess *sp, double);\n" "char *VRT_time_string(const struct sess *sp, double);\n" "const char *VRT_bool_string(const struct sess *sp, unsigned);\n" "const char *VRT_backend_string(const struct sess *sp, const " "struct director *d);\n\n#define VRT_done(sp, hand)\t\t\t\\\n" "\tdo {\t\t\t\t\t\\\n\t\tVRT_handling(sp, hand);\t\t\\\n" "\t\treturn (1);\t\t\t\\\n\t} while (0)\n\nconst char *VRT_WrkStr" "ing(const struct sess *sp, const char *p, ...);\n" ); /* ../include/vrt_obj.h */ VSB_cat(sb, "/*\n * NB: This file is machine generated, DO " "NOT EDIT!\n *\n * Edit and run generate.py instead\n" " */\nstruct sockaddr_storage * VRT_r_client_ip(const struct " "sess *);\nconst char * VRT_r_client_identity(struct sess *);\n" "void VRT_l_client_identity(struct sess *, const char *, ...);\n" "struct sockaddr_storage * VRT_r_server_ip(struct sess *);\n" "const char * VRT_r_server_hostname(struct sess *);\n" "const char * VRT_r_server_identity(struct sess *);\n" "int VRT_r_server_port(struct sess *);\nconst char * VRT_r_req_re" "quest(const struct sess *);\nvoid VRT_l_req_request(const " "struct sess *, const char *, ...);\nconst char * VRT_r_req_url(c" "onst struct sess *);\nvoid VRT_l_req_url(const struct sess " "*, const char *, ...);\nconst char * VRT_r_req_proto(const " "struct sess *);\nvoid VRT_l_req_proto(const struct sess *, " "const char *, ...);\nstruct director * VRT_r_req_backend(struct " "sess *);\nvoid VRT_l_req_backend(struct sess *, struct director " "*);\nint VRT_r_req_restarts(const struct sess *);\n" "int VRT_r_req_esi_level(const struct sess *);\ndouble VRT_r_req_" "ttl(struct sess *);\nvoid VRT_l_req_ttl(struct sess *, double);\n" "double VRT_r_req_grace(struct sess *);\nvoid VRT_l_req_grace(str" "uct sess *, double);\ndouble VRT_r_req_keep(struct sess *);\n" "void VRT_l_req_keep(struct sess *, double);\nconst char * " "VRT_r_req_xid(struct sess *);\nunsigned VRT_r_req_esi(struct " "sess *);\nvoid VRT_l_req_esi(struct sess *, unsigned);\n" "unsigned VRT_r_req_can_gzip(struct sess *);\nunsigned VRT_r_req_" "backend_healthy(const struct sess *);\nunsigned VRT_r_req_hash_i" "gnore_busy(struct sess *);\nvoid VRT_l_req_hash_ignore_busy(stru" "ct sess *, unsigned);\nunsigned VRT_r_req_hash_always_miss(struc" "t sess *);\nvoid VRT_l_req_hash_always_miss(struct sess *, " "unsigned);\nconst char * VRT_r_bereq_request(const struct " "sess *);\nvoid VRT_l_bereq_request(const struct sess *, const " "char *, ...);\nconst char * VRT_r_bereq_url(const struct sess " "*);\nvoid VRT_l_bereq_url(const struct sess *, const char " "*, ...);\nconst char * VRT_r_bereq_proto(const struct sess " "*);\nvoid VRT_l_bereq_proto(const struct sess *, const char " "*, ...);\ndouble VRT_r_bereq_connect_timeout(struct sess *);\n" "void VRT_l_bereq_connect_timeout(struct sess *, double);\n" "double VRT_r_bereq_first_byte_timeout(struct sess *);\n" "void VRT_l_bereq_first_byte_timeout(struct sess *, double);\n" "double VRT_r_bereq_between_bytes_timeout(struct sess *);\n" "void VRT_l_bereq_between_bytes_timeout(struct sess *, double);\n" "const char * VRT_r_beresp_proto(const struct sess *);\n" "void VRT_l_beresp_proto(const struct sess *, const char *, " "...);\nvoid VRT_l_beresp_saintmode(const struct sess *, double);" "\nint VRT_r_beresp_status(const struct sess *);\n" "void VRT_l_beresp_status(const struct sess *, int);\n" "const char * VRT_r_beresp_response(const struct sess *);\n" "void VRT_l_beresp_response(const struct sess *, const char " "*, ...);\nunsigned VRT_r_beresp_do_esi(const struct sess *);\n" "void VRT_l_beresp_do_esi(const struct sess *, unsigned);\n" "unsigned VRT_r_beresp_do_stream(const struct sess *);\n" "void VRT_l_beresp_do_stream(const struct sess *, unsigned);\n" "unsigned VRT_r_beresp_do_gzip(const struct sess *);\n" "void VRT_l_beresp_do_gzip(const struct sess *, unsigned);\n" "unsigned VRT_r_beresp_do_gunzip(const struct sess *);\n" "void VRT_l_beresp_do_gunzip(const struct sess *, unsigned);\n" "double VRT_r_beresp_ttl(struct sess *);\nvoid VRT_l_beresp_ttl(s" "truct sess *, double);\ndouble VRT_r_beresp_grace(struct sess " "*);\nvoid VRT_l_beresp_grace(struct sess *, double);\n" "double VRT_r_beresp_keep(struct sess *);\nvoid VRT_l_beresp_keep" "(struct sess *, double);\nconst char * VRT_r_beresp_backend_name" "(const struct sess *);\nstruct sockaddr_storage * VRT_r_beresp_b" "ackend_ip(const struct sess *);\nint VRT_r_beresp_backend_port(c" "onst struct sess *);\nconst char * VRT_r_beresp_storage(struct " "sess *);\nvoid VRT_l_beresp_storage(struct sess *, const char " "*, ...);\nconst char * VRT_r_obj_proto(const struct sess *);\n" "void VRT_l_obj_proto(const struct sess *, const char *, ...);\n" "int VRT_r_obj_status(const struct sess *);\nvoid VRT_l_obj_statu" "s(const struct sess *, int);\nconst char * VRT_r_obj_response(co" "nst struct sess *);\nvoid VRT_l_obj_response(const struct " "sess *, const char *, ...);\nint VRT_r_obj_hits(const struct " "sess *);\ndouble VRT_r_obj_ttl(struct sess *);\nvoid VRT_l_obj_t" "tl(struct sess *, double);\ndouble VRT_r_obj_grace(struct " "sess *);\nvoid VRT_l_obj_grace(struct sess *, double);\n" "double VRT_r_obj_keep(struct sess *);\nvoid VRT_l_obj_keep(struc" "t sess *, double);\ndouble VRT_r_obj_lastuse(const struct " "sess *);\nconst char * VRT_r_resp_proto(const struct sess " "*);\nvoid VRT_l_resp_proto(const struct sess *, const char " "*, ...);\nint VRT_r_resp_status(const struct sess *);\n" "void VRT_l_resp_status(const struct sess *, int);\n" "const char * VRT_r_resp_response(const struct sess *);\n" "void VRT_l_resp_response(const struct sess *, const char *, " "...);\ndouble VRT_r_now(const struct sess *);\ndouble VRT_Stv_fr" "ee_space(const char *);\ndouble VRT_Stv_used_space(const char " "*);\nunsigned VRT_Stv_happy(const char *);\n" ); }
/* * Quote a string */ void VSB_quote_pfx(struct vsb *s, const char *pfx, const void *v, int len, int how) { const char *p; const char *q; int quote = 0; int nl = 0; const unsigned char *u, *w; assert(v != NULL); if (len == -1) len = strlen(v); if (len == 0 && (how & VSB_QUOTE_CSTR)) { VSB_printf(s, "%s\"\"", pfx); return; } else if (len == 0) return; VSB_cat(s, pfx); if (how & VSB_QUOTE_HEX) { u = v; for (w = u; w < u + len; w++) if (*w != 0x00) break; VSB_printf(s, "0x"); if (w == u + len && len > 4) { VSB_printf(s, "0...0"); } else { for (w = u; w < u + len; w++) VSB_printf(s, "%02x", *w); } return; } p = v; for (q = p; q < p + len; q++) { if (!isgraph(*q) || *q == '"' || *q == '\\') { quote++; break; } } if (!quote && !(how & (VSB_QUOTE_JSON|VSB_QUOTE_CSTR))) { (void)VSB_bcat(s, p, len); if ((how & (VSB_QUOTE_UNSAFE|VSB_QUOTE_NONL)) && p[len-1] != '\n') (void)VSB_putc(s, '\n'); return; } if (how & VSB_QUOTE_CSTR) (void)VSB_putc(s, '"'); for (q = p; q < p + len; q++) { if (nl) VSB_cat(s, pfx); nl = 0; switch (*q) { case '?': if (how & VSB_QUOTE_CSTR) (void)VSB_putc(s, '\\'); (void)VSB_putc(s, *q); break; case ' ': (void)VSB_putc(s, *q); break; case '\\': case '"': if (!(how & VSB_QUOTE_UNSAFE)) (void)VSB_putc(s, '\\'); (void)VSB_putc(s, *q); break; case '\n': if (how & VSB_QUOTE_CSTR) { (void)VSB_printf(s, "\\n\"\n%s\t\"", pfx); } else if (how & (VSB_QUOTE_NONL|VSB_QUOTE_UNSAFE)) { (void)VSB_printf(s, "\n"); nl = 1; } else { (void)VSB_printf(s, "\\n"); } break; case '\r': (void)VSB_cat(s, "\\r"); break; case '\t': (void)VSB_cat(s, "\\t"); break; case '\v': (void)VSB_cat(s, "\\v"); break; default: /* XXX: Implement VSB_QUOTE_JSON */ if (isgraph(*q)) (void)VSB_putc(s, *q); else if (how & VSB_QUOTE_ESCHEX) (void)VSB_printf(s, "\\x%02x", *q & 0xff); else (void)VSB_printf(s, "\\%03o", *q & 0xff); break; } } if (how & VSB_QUOTE_CSTR) (void)VSB_putc(s, '"'); if ((how & (VSB_QUOTE_NONL|VSB_QUOTE_UNSAFE)) && !nl) (void)VSB_putc(s, '\n'); }
static void cmd_http_txreq(CMD_ARGS) { struct http *hp; const char *req = "GET"; const char *url = "/"; const char *proto = "HTTP/1.1"; const char *body = NULL; (void)cmd; (void)vl; CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC); ONLY_CLIENT(hp, av); assert(!strcmp(av[0], "txreq")); av++; VSB_clear(hp->vsb); for(; *av != NULL; av++) { if (!strcmp(*av, "-url")) { url = av[1]; av++; } else if (!strcmp(*av, "-proto")) { proto = av[1]; av++; } else if (!strcmp(*av, "-req")) { req = av[1]; av++; } else break; } VSB_printf(hp->vsb, "%s %s %s%s", req, url, proto, nl); for(; *av != NULL; av++) { if (!strcmp(*av, "-hdr")) { VSB_printf(hp->vsb, "%s%s", av[1], nl); av++; } else break; } for(; *av != NULL; av++) { if (!strcmp(*av, "-body")) { AZ(body); body = av[1]; av++; } else if (!strcmp(*av, "-bodylen")) { AZ(body); body = synth_body(av[1], 0); av++; } else break; } if (*av != NULL) vtc_log(hp->vl, 0, "Unknown http txreq spec: %s\n", *av); if (body != NULL) VSB_printf(hp->vsb, "Content-Length: %ju%s", (uintmax_t)strlen(body), nl); VSB_cat(hp->vsb, nl); if (body != NULL) { VSB_cat(hp->vsb, body); VSB_cat(hp->vsb, nl); } http_write(hp, 4, "txreq"); }
static void cmd_http_txresp(CMD_ARGS) { struct http *hp; const char *proto = "HTTP/1.1"; const char *status = "200"; const char *msg = "Ok"; int bodylen = 0; char *b, *c; char *body = NULL, *nullbody; int nolen = 0; (void)cmd; (void)vl; CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC); ONLY_SERVER(hp, av); assert(!strcmp(av[0], "txresp")); av++; VSB_clear(hp->vsb); /* send a "Content-Length: 0" header unless something else happens */ REPLACE(body, ""); nullbody = body; for(; *av != NULL; av++) { if (!strcmp(*av, "-proto")) { proto = av[1]; av++; } else if (!strcmp(*av, "-status")) { status = av[1]; av++; } else if (!strcmp(*av, "-msg")) { msg = av[1]; av++; continue; } else break; } VSB_printf(hp->vsb, "%s %s %s%s", proto, status, msg, nl); for(; *av != NULL; av++) { if (!strcmp(*av, "-nolen")) { nolen = 1; } else if (!strcmp(*av, "-hdr")) { VSB_printf(hp->vsb, "%s%s", av[1], nl); av++; } else break; } for(; *av != NULL; av++) { if (!strcmp(*av, "-body")) { assert(body == nullbody); REPLACE(body, av[1]); AN(body); av++; bodylen = strlen(body); for (b = body; *b != '\0'; b++) { if(*b == '\\' && b[1] == '0') { *b = '\0'; for(c = b+1; *c != '\0'; c++) { *c = c[1]; } b++; bodylen--; } } } else if (!strcmp(*av, "-bodylen")) { assert(body == nullbody); body = synth_body(av[1], 0); bodylen = strlen(body); av++; } else if (!strcmp(*av, "-gzipresidual")) { hp->gzipresidual = strtoul(av[1], NULL, 0); av++; } else if (!strcmp(*av, "-gziplevel")) { hp->gziplevel = strtoul(av[1], NULL, 0); av++; } else if (!strcmp(*av, "-gziplen")) { assert(body == nullbody); b = synth_body(av[1], 1); gzip_body(hp, b, &body, &bodylen); VSB_printf(hp->vsb, "Content-Encoding: gzip%s", nl); // vtc_hexdump(hp->vl, 4, "gzip", (void*)body, bodylen); av++; } else if (!strcmp(*av, "-gzipbody")) { assert(body == nullbody); gzip_body(hp, av[1], &body, &bodylen); VSB_printf(hp->vsb, "Content-Encoding: gzip%s", nl); // vtc_hexdump(hp->vl, 4, "gzip", (void*)body, bodylen); av++; } else break; } if (*av != NULL) vtc_log(hp->vl, 0, "Unknown http txresp spec: %s\n", *av); if (body != NULL && !nolen) VSB_printf(hp->vsb, "Content-Length: %d%s", bodylen, nl); VSB_cat(hp->vsb, nl); if (body != NULL) VSB_bcat(hp->vsb, body, bodylen); http_write(hp, 4, "txresp"); }