VCL_VOID VRT_l_beresp_storage_hint(VRT_CTX, const char *str, ...) { const char *p; va_list ap; uintptr_t sn; VCL_STEVEDORE stv; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC); sn = WS_Snapshot(ctx->ws); va_start(ap, str); p = VRT_String(ctx->ws, NULL, str, ap); va_end(ap); if (p == NULL) { VSLb(ctx->vsl, SLT_LostHeader, "storage_hint"); WS_Reset(ctx->ws, sn); WS_MarkOverflow(ctx->ws); return; } stv = VRT_stevedore(p); if (stv != NULL) ctx->bo->storage = stv; WS_Reset(ctx->ws, sn); }
void * WS_Copy(struct ws *ws, const void *str, int len) { char *r; unsigned bytes; WS_Assert(ws); assert(ws->r == NULL); if (len == -1) len = strlen(str) + 1; assert(len >= 0); bytes = PRNDUP((unsigned)len); if (ws->f + bytes > ws->e) { WS_MarkOverflow(ws); WS_Assert(ws); return(NULL); } r = ws->f; ws->f += bytes; memcpy(r, str, len); DSL(DBG_WORKSPACE, 0, "WS_Copy(%p, %d) = %p", ws, len, r); WS_Assert(ws); return (r); }
vmod_log(VRT_CTX, const char *fmt, ...) { const char *p; va_list ap; uintptr_t sn; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); sn = WS_Snapshot(ctx->ws); va_start(ap, fmt); p = VRT_String(ctx->ws, NULL, fmt, ap); va_end(ap); if (p == NULL) { WS_MarkOverflow(ctx->ws); WS_Reset(ctx->ws, sn); return; } AN(p); if (ctx->vsl != NULL) VSLb(ctx->vsl, SLT_VCL_Log, "%s", p); else VSL(SLT_VCL_Log, 0, "%s", p); WS_Reset(ctx->ws, sn); }
static void http_fail(const struct http *hp) { VSC_C_main->losthdr++; VSLb(hp->vsl, SLT_Error, "out of workspace (%s)", hp->ws->id); WS_MarkOverflow(hp->ws); }
void vmod_workspace_overflow(VRT_CTX, VCL_ENUM which) { struct ws *ws; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); ws = wsfind(ctx, which); WS_Assert(ws); WS_MarkOverflow(ws); }
static void vrt_do_string(const struct http *hp, int fld, const char *err, const char *p, va_list ap) { const char *b; CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); b = VRT_String(hp->ws, NULL, p, ap); if (b == NULL || *b == '\0') { VSLb(hp->vsl, SLT_LostHeader, "%s", err); WS_MarkOverflow(hp->ws); return; } http_SetH(hp, fld, b); }
void VRT_l_beresp_storage_hint(const struct vrt_ctx *ctx, const char *str, ...) { va_list ap; const char *b; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC); va_start(ap, str); b = VRT_String(ctx->bo->ws, NULL, str, ap); // XXX: ctx->ws ? va_end(ap); if (b == NULL) { VSLb(ctx->vsl, SLT_LostHeader, "storage.hint"); WS_MarkOverflow(ctx->bo->beresp->ws); return; } ctx->bo->storage_hint = b; }
void VRT_l_client_identity(const struct vrt_ctx *ctx, const char *str, ...) { va_list ap; const char *b; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); va_start(ap, str); b = VRT_String(ctx->req->http->ws, NULL, str, ap); va_end(ap); if (b == NULL) { VSLb(ctx->vsl, SLT_LostHeader, "client.identity"); WS_MarkOverflow(ctx->req->http->ws); return; } ctx->req->client_identity = b; }
void * WS_Alloc(struct ws *ws, unsigned bytes) { char *r; WS_Assert(ws); bytes = PRNDUP(bytes); assert(ws->r == NULL); if (ws->f + bytes > ws->e) { WS_MarkOverflow(ws); return(NULL); } r = ws->f; ws->f += bytes; DSL(DBG_WORKSPACE, 0, "WS_Alloc(%p, %u) = %p", ws, bytes, r); WS_Assert(ws); return (r); }
void V1L_Reserve(struct worker *wrk, struct ws *ws, int *fd, struct vsl_log *vsl, double t0) { struct v1l *v1l; unsigned u; void *res; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); AZ(wrk->v1l); if (WS_Overflowed(ws)) return; res = WS_Snapshot(ws); v1l = WS_Alloc(ws, sizeof *v1l); if (v1l == NULL) return; INIT_OBJ(v1l, V1L_MAGIC); v1l->ws = ws; v1l->res = res; u = WS_Reserve(ws, 0); u = PRNDDN(u); u /= sizeof(struct iovec); if (u == 0) { WS_Release(ws, 0); WS_MarkOverflow(ws); return; } else if (u > IOV_MAX) u = IOV_MAX; v1l->iov = (void*)PRNDUP(ws->f); v1l->siov = u; v1l->ciov = u; v1l->werr = 0; v1l->liov = 0; v1l->niov = 0; v1l->wfd = fd; v1l->t0 = t0; v1l->vsl = vsl; wrk->v1l = v1l; }
static void vrt_do_string(VRT_CTX, struct http *hp, int fld, const char *err, const char *p, va_list ap) { const char *b; CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); b = VRT_String(hp->ws, NULL, p, ap); if (b == NULL) { VRT_fail(ctx, "Workspace overflow (%s)", err); WS_MarkOverflow(hp->ws); return; } if (*b == '\0') { VRT_fail(ctx, "Setting %s to empty string", err); return; } http_SetH(hp, fld, b); }
unsigned WS_Reserve(struct ws *ws, unsigned bytes) { unsigned b2; WS_Assert(ws); assert(ws->r == NULL); b2 = PRNDDN(ws->e - ws->f); if (bytes != 0 && bytes < b2) b2 = PRNDUP(bytes); if (ws->f + b2 > ws->e) { WS_MarkOverflow(ws); return (0); } ws->r = ws->f + b2; DSL(DBG_WORKSPACE, 0, "WS_Reserve(%p, %u/%u) = %u", ws, b2, bytes, pdiff(ws->f, ws->r)); WS_Assert(ws); return (pdiff(ws->f, ws->r)); }
void * WS_Printf(struct ws *ws, const char *fmt, ...) { unsigned u, v; va_list ap; char *p; WS_Assert(ws); assert(ws->r == NULL); u = WS_Reserve(ws, 0); p = ws->f; va_start(ap, fmt); v = vsnprintf(p, u, fmt, ap); va_end(ap); if (v >= u) { WS_Release(ws, 0); WS_MarkOverflow(ws); p = NULL; } else { WS_Release(ws, v + 1); } return (p); }
static const char * vmod_updown(VRT_CTX, int up, const char *s, va_list ap) { unsigned u; char *b, *e; const char *p; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); u = WS_Reserve(ctx->ws, 0); e = b = ctx->ws->f; e += u; p = s; while (p != vrt_magic_string_end && b < e) { if (p != NULL) { for (; b < e && *p != '\0'; p++) if (up) *b++ = (char)toupper(*p); else *b++ = (char)tolower(*p); } p = va_arg(ap, const char *); } if (b < e) *b = '\0'; b++; if (b > e) { WS_MarkOverflow(ctx->ws); WS_Release(ctx->ws, 0); return (NULL); } else { e = b; b = ctx->ws->f; WS_Release(ctx->ws, e - b); return (b); } }
vmod_querysort(const struct vrt_ctx *ctx, VCL_STRING url) { const char *cq, *cu; char *p, *r; const char **pp; const char **pe; int np; int i; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); if (url == NULL) return (NULL); /* Split :query from :url */ cu = strchr(url, '?'); if (cu == NULL) return (url); /* Spot single-param queries */ cq = strchr(cu, '&'); if (cq == NULL) return (url); r = WS_Copy(ctx->ws, url, -1); if (r == NULL) return (url); (void)WS_Reserve(ctx->ws, 0); /* We trust cache_ws.c to align sensibly */ pp = (const char**)(void*)(ctx->ws->f); pe = (const char**)(void*)(ctx->ws->e); if (pp + 4 > pe) { WS_Release(ctx->ws, 0); WS_MarkOverflow(ctx->ws); return (url); } /* Collect params as pointer pairs */ np = 0; pp[np++] = 1 + cu; for (cq = 1 + cu; *cq != '\0'; cq++) { if (*cq == '&') { if (pp + 3 > pe) { WS_Release(ctx->ws, 0); WS_MarkOverflow(ctx->ws); return (url); } pp[np++] = cq; /* Skip trivially empty params */ while(cq[1] == '&') cq++; pp[np++] = cq + 1; } } pp[np++] = cq; assert(!(np & 1)); qsort(pp, np / 2, sizeof(*pp) * 2, compa); /* Emit sorted params */ p = 1 + r + (cu - url); cq = ""; for (i = 0; i < np; i += 2) { /* Ignore any edge-case zero length params */ if (pp[i + 1] == pp[i]) continue; assert(pp[i + 1] > pp[i]); if (*cq) *p++ = *cq; memcpy(p, pp[i], pp[i + 1] - pp[i]); p += pp[i + 1] - pp[i]; cq = "&"; } *p = '\0'; WS_Release(ctx->ws, 0); return (r); }