static void vcc_ParseHostDef(struct vcc *tl, const struct token *t_be, const char *vgcname) { struct token *t_field; struct token *t_val; struct token *t_host = NULL; struct token *t_port = NULL; struct token *t_hosthdr = NULL; struct fld_spec *fs; struct inifin *ifp; struct vsb *vsb; char *p; unsigned u; double t; fs = vcc_FldSpec(tl, "!host", "?port", "?host_header", "?connect_timeout", "?first_byte_timeout", "?between_bytes_timeout", "?probe", "?max_connections", "?proxy_header", NULL); SkipToken(tl, '{'); vsb = VSB_new_auto(); AN(vsb); tl->fb = vsb; Fb(tl, 0, "\nstatic const struct vrt_backend vgc_dir_priv_%s = {\n", vgcname); Fb(tl, 0, "\t.magic = VRT_BACKEND_MAGIC,\n"); Fb(tl, 0, "\t.vcl_name = \"%.*s", PF(t_be)); Fb(tl, 0, "\",\n"); /* Check for old syntax */ if (tl->t->tok == ID && vcc_IdIs(tl->t, "set")) { VSB_printf(tl->sb, "NB: Backend Syntax has changed:\n" "Remove \"set\" and \"backend\" in front" " of backend fields.\n" ); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at "); vcc_ErrWhere(tl, tl->t); return; } while (tl->t->tok != '}') { vcc_IsField(tl, &t_field, fs); ERRCHK(tl); if (vcc_IdIs(t_field, "host")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_host = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "port")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_port = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "host_header")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_hosthdr = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "connect_timeout")) { Fb(tl, 0, "\t.connect_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "first_byte_timeout")) { Fb(tl, 0, "\t.first_byte_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "between_bytes_timeout")) { Fb(tl, 0, "\t.between_bytes_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "max_connections")) { u = vcc_UintVal(tl); ERRCHK(tl); SkipToken(tl, ';'); Fb(tl, 0, "\t.max_connections = %u,\n", u); } else if (vcc_IdIs(t_field, "proxy_header")) { t_val = tl->t; u = vcc_UintVal(tl); ERRCHK(tl); if (u != 1 && u != 2) { VSB_printf(tl->sb, ".proxy_header must be 1 or 2\n"); vcc_ErrWhere(tl, t_val); return; } SkipToken(tl, ';'); Fb(tl, 0, "\t.proxy_header = %u,\n", u); } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == '{') { vcc_ParseProbeSpec(tl, NULL, &p); Fb(tl, 0, "\t.probe = &%s,\n", p); ERRCHK(tl); } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == ID) { if (VCC_FindSymbol(tl, tl->t, SYM_PROBE) == NULL) { VSB_printf(tl->sb, "Probe %.*s not found\n", PF(tl->t)); vcc_ErrWhere(tl, tl->t); return; } Fb(tl, 0, "\t.probe = &vgc_probe_%.*s,\n", PF(tl->t)); vcc_AddRef(tl, tl->t, SYM_PROBE); vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "probe")) { VSB_printf(tl->sb, "Expected '{' or name of probe, got "); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at\n"); vcc_ErrWhere(tl, tl->t); return; } else { ErrInternal(tl); return; } } vcc_FieldsOk(tl, fs); ERRCHK(tl); /* Check that the hostname makes sense */ assert(t_host != NULL); Emit_Sockaddr(tl, t_host, t_port); ERRCHK(tl); ExpectErr(tl, '}'); /* We have parsed it all, emit the ident string */ /* Emit the hosthdr field, fall back to .host if not specified */ Fb(tl, 0, "\t.hosthdr = "); if (t_hosthdr != NULL) EncToken(tl->fb, t_hosthdr); else EncToken(tl->fb, t_host); Fb(tl, 0, ",\n"); /* Close the struct */ Fb(tl, 0, "};\n"); vcc_NextToken(tl); tl->fb = NULL; AZ(VSB_finish(vsb)); Fh(tl, 0, "%s", VSB_data(vsb)); VSB_destroy(&vsb); ifp = New_IniFin(tl); VSB_printf(ifp->ini, "\t%s =\n\t VRT_new_backend(ctx, &vgc_dir_priv_%s);", vgcname, vgcname); }
static void vcc_ParseHostDef(struct vcc *tl, const struct token *t_be, const char *vgcname) { struct token *t_field; struct token *t_val; struct token *t_host = NULL; struct token *t_port = NULL; struct token *t_path = NULL; struct token *t_hosthdr = NULL; struct symbol *pb; struct token *t_did = NULL; struct fld_spec *fs; struct inifin *ifp; struct vsb *vsb; char *p; unsigned u; double t; fs = vcc_FldSpec(tl, "?host", "?port", "?path", "?host_header", "?connect_timeout", "?first_byte_timeout", "?between_bytes_timeout", "?probe", "?max_connections", "?proxy_header", NULL); SkipToken(tl, '{'); vsb = VSB_new_auto(); AN(vsb); tl->fb = vsb; Fb(tl, 0, "\nstatic const struct vrt_backend vgc_dir_priv_%s = {\n", vgcname); Fb(tl, 0, "\t.magic = VRT_BACKEND_MAGIC,\n"); Fb(tl, 0, "\t.vcl_name = \"%.*s", PF(t_be)); Fb(tl, 0, "\",\n"); /* Check for old syntax */ if (tl->t->tok == ID && vcc_IdIs(tl->t, "set")) { VSB_printf(tl->sb, "NB: Backend Syntax has changed:\n" "Remove \"set\" and \"backend\" in front" " of backend fields.\n" ); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at "); vcc_ErrWhere(tl, tl->t); return; } while (tl->t->tok != '}') { vcc_IsField(tl, &t_field, fs); ERRCHK(tl); if (vcc_IdIs(t_field, "host")) { vcc_Redef(tl, "Address", &t_did, t_field); ERRCHK(tl); ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_host = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "port")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_port = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "path")) { if (tl->syntax < VCL_41) { VSB_printf(tl->sb, "Unix socket backends only supported" " in VCL4.1 and higher.\n"); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at "); vcc_ErrWhere(tl, tl->t); return; } vcc_Redef(tl, "Address", &t_did, t_field); ERRCHK(tl); ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_path = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "host_header")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_hosthdr = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "connect_timeout")) { Fb(tl, 0, "\t.connect_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "first_byte_timeout")) { Fb(tl, 0, "\t.first_byte_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "between_bytes_timeout")) { Fb(tl, 0, "\t.between_bytes_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "max_connections")) { u = vcc_UintVal(tl); ERRCHK(tl); SkipToken(tl, ';'); Fb(tl, 0, "\t.max_connections = %u,\n", u); } else if (vcc_IdIs(t_field, "proxy_header")) { t_val = tl->t; u = vcc_UintVal(tl); ERRCHK(tl); if (u != 1 && u != 2) { VSB_printf(tl->sb, ".proxy_header must be 1 or 2\n"); vcc_ErrWhere(tl, t_val); return; } SkipToken(tl, ';'); Fb(tl, 0, "\t.proxy_header = %u,\n", u); } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == '{') { vcc_ParseProbeSpec(tl, NULL, &p); Fb(tl, 0, "\t.probe = %s,\n", p); ERRCHK(tl); } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == ID) { if (vcc_IdIs(tl->t, "default")) { vcc_NextToken(tl); (void)vcc_default_probe(tl); } else { pb = VCC_SymbolGet(tl, SYM_PROBE, "Probe not found", XREF_REF); ERRCHK(tl); AN(pb); Fb(tl, 0, "\t.probe = %s,\n", pb->rname); } SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "probe")) { VSB_printf(tl->sb, "Expected '{' or name of probe, got "); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at\n"); vcc_ErrWhere(tl, tl->t); return; } else { ErrInternal(tl); return; } } vcc_FieldsOk(tl, fs); ERRCHK(tl); if (t_host == NULL && t_path == NULL) { VSB_printf(tl->sb, "Expected .host or .path.\n"); vcc_ErrWhere(tl, t_be); return; } assert(t_host != NULL || t_path != NULL); if (t_host != NULL) /* Check that the hostname makes sense */ Emit_Sockaddr(tl, t_host, t_port); else /* Check that the path can be a legal UDS */ Emit_UDS_Path(tl, t_path, "Backend path"); ERRCHK(tl); ExpectErr(tl, '}'); /* We have parsed it all, emit the ident string */ /* Emit the hosthdr field, fall back to .host if not specified */ /* If .path is specified, set "0.0.0.0". */ Fb(tl, 0, "\t.hosthdr = "); if (t_hosthdr != NULL) EncToken(tl->fb, t_hosthdr); else if (t_host != NULL) EncToken(tl->fb, t_host); else Fb(tl, 0, "\"0.0.0.0\""); Fb(tl, 0, ",\n"); /* Close the struct */ Fb(tl, 0, "};\n"); vcc_NextToken(tl); tl->fb = NULL; AZ(VSB_finish(vsb)); Fh(tl, 0, "%s", VSB_data(vsb)); VSB_destroy(&vsb); ifp = New_IniFin(tl); VSB_printf(ifp->ini, "\t%s =\n\t VRT_new_backend_clustered(ctx, vsc_cluster,\n" "\t\t&vgc_dir_priv_%s);", vgcname, vgcname); VSB_printf(ifp->fin, "\t\tVRT_delete_backend(ctx, &%s);", vgcname); }
static void vcc_ParseHostDef(struct vcc *tl, int serial, const char *vgcname) { struct token *t_field; struct token *t_host = NULL; struct token *t_port = NULL; struct token *t_hosthdr = NULL; unsigned saint = UINT_MAX; struct fld_spec *fs; struct vsb *vsb; unsigned u; double t; Fh(tl, 1, "\n#define VGC_backend_%s %d\n", vgcname, tl->ndirector); fs = vcc_FldSpec(tl, "!host", "?port", "?host_header", "?connect_timeout", "?first_byte_timeout", "?between_bytes_timeout", "?probe", "?max_connections", "?saintmode_threshold", NULL); SkipToken(tl, '{'); vsb = VSB_new_auto(); AN(vsb); tl->fb = vsb; Fb(tl, 0, "\nstatic const struct vrt_backend vgc_dir_priv_%s = {\n", vgcname); Fb(tl, 0, "\t.vcl_name = \"%.*s", PF(tl->t_dir)); if (serial >= 0) Fb(tl, 0, "[%d]", serial); Fb(tl, 0, "\",\n"); /* Check for old syntax */ if (tl->t->tok == ID && vcc_IdIs(tl->t, "set")) { VSB_printf(tl->sb, "NB: Backend Syntax has changed:\n" "Remove \"set\" and \"backend\" in front" " of backend fields.\n" ); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at "); vcc_ErrWhere(tl, tl->t); return; } while (tl->t->tok != '}') { vcc_IsField(tl, &t_field, fs); ERRCHK(tl); if (vcc_IdIs(t_field, "host")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_host = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "port")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_port = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "host_header")) { ExpectErr(tl, CSTR); assert(tl->t->dec != NULL); t_hosthdr = tl->t; vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "connect_timeout")) { Fb(tl, 0, "\t.connect_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "first_byte_timeout")) { Fb(tl, 0, "\t.first_byte_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "between_bytes_timeout")) { Fb(tl, 0, "\t.between_bytes_timeout = "); vcc_Duration(tl, &t); ERRCHK(tl); Fb(tl, 0, "%g,\n", t); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "max_connections")) { u = vcc_UintVal(tl); ERRCHK(tl); SkipToken(tl, ';'); Fb(tl, 0, "\t.max_connections = %u,\n", u); } else if (vcc_IdIs(t_field, "saintmode_threshold")) { u = vcc_UintVal(tl); /* UINT_MAX == magic number to mark as unset, so * not allowed here. */ if (u == UINT_MAX) { VSB_printf(tl->sb, "Value outside allowed range: "); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at\n"); vcc_ErrWhere(tl, tl->t); } ERRCHK(tl); saint = u; SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == '{') { Fb(tl, 0, "\t.probe = &vgc_probe__%d,\n", tl->nprobe); vcc_ParseProbeSpec(tl); ERRCHK(tl); } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == ID) { Fb(tl, 0, "\t.probe = &vgc_probe_%.*s,\n", PF(tl->t)); vcc_AddRef(tl, tl->t, SYM_PROBE); vcc_NextToken(tl); SkipToken(tl, ';'); } else if (vcc_IdIs(t_field, "probe")) { VSB_printf(tl->sb, "Expected '{' or name of probe."); vcc_ErrToken(tl, tl->t); VSB_printf(tl->sb, " at\n"); vcc_ErrWhere(tl, tl->t); return; } else { ErrInternal(tl); return; } } vcc_FieldsOk(tl, fs); ERRCHK(tl); /* Check that the hostname makes sense */ assert(t_host != NULL); if (t_port != NULL) Emit_Sockaddr(tl, t_host, t_port->dec); else Emit_Sockaddr(tl, t_host, "80"); ERRCHK(tl); ExpectErr(tl, '}'); /* We have parsed it all, emit the ident string */ /* Emit the hosthdr field, fall back to .host if not specified */ Fb(tl, 0, "\t.hosthdr = "); if (t_hosthdr != NULL) EncToken(tl->fb, t_hosthdr); else EncToken(tl->fb, t_host); Fb(tl, 0, ",\n"); Fb(tl, 0, "\t.saintmode_threshold = %d,\n",saint); /* Close the struct */ Fb(tl, 0, "};\n"); vcc_NextToken(tl); tl->fb = NULL; AZ(VSB_finish(vsb)); Fh(tl, 0, "%s", VSB_data(vsb)); VSB_delete(vsb); Fi(tl, 0, "\tVRT_init_dir(cli, VCL_conf.director, \"simple\",\n" "\t VGC_backend_%s, &vgc_dir_priv_%s);\n", vgcname, vgcname); Ff(tl, 0, "\tVRT_fini_dir(cli, VGCDIR(%s));\n", vgcname); tl->ndirector++; }