From tfheen at varnish-cache.org Mon Sep 2 10:44:19 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Mon, 02 Sep 2013 12:44:19 +0200 Subject: [master] d15d4a4 Drop no longer used file from Makefile.am Message-ID: commit d15d4a479d326c1e7177e461ce8dea6e7fbc0981 Author: Tollef Fog Heen Date: Mon Sep 2 12:44:16 2013 +0200 Drop no longer used file from Makefile.am diff --git a/doc/sphinx/Makefile.am b/doc/sphinx/Makefile.am index 9818e81..579b6c8 100644 --- a/doc/sphinx/Makefile.am +++ b/doc/sphinx/Makefile.am @@ -161,8 +161,7 @@ EXTRA_DIST = \ users-guide/vcl-saint-and-grace.rst \ users-guide/vcl-syntax.rst \ users-guide/vcl-variables.rst \ - users-guide/websockets.rst \ - include/vcl-backends.rst + users-guide/websockets.rst dist-hook: From phk at varnish-cache.org Tue Sep 3 08:16:46 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 03 Sep 2013 10:16:46 +0200 Subject: [master] 8bfe8e0 Fix the last oc->oh tests to look at OC_F_PRIVATE instead Message-ID: commit 8bfe8e0da21c65d477f8c1ba9f5071b8b3cca149 Author: Poul-Henning Kamp Date: Tue Sep 3 08:16:24 2013 +0000 Fix the last oc->oh tests to look at OC_F_PRIVATE instead diff --git a/bin/varnishd/cache/cache_busyobj.c b/bin/varnishd/cache/cache_busyobj.c index cb22c54..0920b7e 100644 --- a/bin/varnishd/cache/cache_busyobj.c +++ b/bin/varnishd/cache/cache_busyobj.c @@ -168,7 +168,7 @@ VBO_DerefBusyObj(struct worker *wrk, struct busyobj **pbo) *pbo = NULL; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); CHECK_OBJ_ORNULL(bo->fetch_obj, OBJECT_MAGIC); - if (bo->fetch_obj != NULL && bo->fetch_obj->objcore->objhead != NULL) { + if (bo->fetch_obj != NULL) { oc = bo->fetch_obj->objcore; CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); CHECK_OBJ_NOTNULL(oc->objhead, OBJHEAD_MAGIC); diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index d928603..441ce2a 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -197,8 +197,8 @@ vbf_stp_fetchhdr(struct worker *wrk, struct busyobj *bo) bo->exp.entered = W_TIM_real(wrk); RFC2616_Ttl(bo); - /* pass from vclrecv{} has negative TTL */ - if (bo->fetch_objcore->objhead == NULL) + /* private objects have negative TTL */ + if (bo->fetch_objcore->flags & OC_F_PRIVATE) bo->exp.ttl = -1.; AZ(bo->do_esi); @@ -299,7 +299,7 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) else if (bo->is_gzip) bo->vfp = &vfp_testgzip; - if (bo->fetch_objcore->objhead == NULL) + if (bo->fetch_objcore->flags & OC_F_PRIVATE) AN(bo->uncacheable); /* No reason to try streaming a non-existing body */ @@ -310,7 +310,7 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) bo->uncacheable ? HTTPH_R_PASS : HTTPH_A_INS, &nhttp); /* Create Vary instructions */ - if (bo->fetch_objcore->objhead != NULL) { + if (!(bo->fetch_objcore->flags & OC_F_PRIVATE)) { varyl = VRY_Create(bo, &vary); if (varyl > 0) { AN(vary); @@ -423,6 +423,7 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) VBO_setstate(bo, BOS_FETCHING); V1F_fetch_body(wrk, bo); + HSH_Complete(obj->objcore); assert(bo->refcount >= 1); diff --git a/bin/varnishd/cache/cache_http1_fetch.c b/bin/varnishd/cache/cache_http1_fetch.c index 2d9928c..01511e8 100644 --- a/bin/varnishd/cache/cache_http1_fetch.c +++ b/bin/varnishd/cache/cache_http1_fetch.c @@ -447,7 +447,5 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo) "Content-Length: %zd", obj->len); } } - if (obj->objcore->objhead != NULL) - HSH_Complete(obj->objcore); bo->stats = NULL; } diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 29ae0e4..d66c3de 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -206,7 +206,7 @@ cnt_deliver(struct worker *wrk, struct req *req) } req->t_resp = W_TIM_real(wrk); - if (req->obj->objcore->objhead != NULL) { + if (!(req->obj->objcore->flags & OC_F_PRIVATE)) { if ((req->t_resp - req->obj->last_lru) > cache_param->lru_timeout && EXP_Touch(req->obj->objcore)) From phk at varnish-cache.org Tue Sep 3 08:25:47 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 03 Sep 2013 10:25:47 +0200 Subject: [master] 1417f9d Make bans depend on OC_F_PRIVATE Message-ID: commit 1417f9d0656d1e29a5d3339fa3ad64237986992a Author: Poul-Henning Kamp Date: Tue Sep 3 08:25:38 2013 +0000 Make bans depend on OC_F_PRIVATE diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c index 9abe891..6fd51f6 100644 --- a/bin/varnishd/cache/cache_hash.c +++ b/bin/varnishd/cache/cache_hash.c @@ -655,7 +655,10 @@ HSH_Unbusy(struct dstat *ds, struct objcore *oc) CHECK_OBJ(oh, OBJHEAD_MAGIC); AN(oc->flags & OC_F_BUSY); - AN(oc->ban); + if (oc->flags & OC_F_PRIVATE) + AZ(oc->ban); + else + AN(oc->ban); assert(oh->refcnt > 0); /* XXX: pretouch neighbors on oh->objcs to prevent page-on under mtx */ diff --git a/bin/varnishd/storage/stevedore.c b/bin/varnishd/storage/stevedore.c index 407470e..af14533 100644 --- a/bin/varnishd/storage/stevedore.c +++ b/bin/varnishd/storage/stevedore.c @@ -289,7 +289,7 @@ STV_MkObject(struct stevedore *stv, struct busyobj *bo, o->objcore = bo->fetch_objcore; bo->fetch_objcore = NULL; /* refcnt follows pointer. */ - if (o->objcore->objhead != NULL) + if (!(o->objcore->flags & OC_F_PRIVATE)) BAN_NewObjCore(o->objcore); o->objcore->methods = &default_oc_methods; From phk at varnish-cache.org Tue Sep 3 09:29:15 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 03 Sep 2013 11:29:15 +0200 Subject: [master] 5b339ac Leave bo->fetch_objcore intact, even as the refcount moves to the object. Message-ID: commit 5b339acd19a25bd453f5d9858c26ed0c4f5ac286 Author: Poul-Henning Kamp Date: Tue Sep 3 09:28:53 2013 +0000 Leave bo->fetch_objcore intact, even as the refcount moves to the object. diff --git a/bin/varnishd/cache/cache_busyobj.c b/bin/varnishd/cache/cache_busyobj.c index 0920b7e..4b6c37f 100644 --- a/bin/varnishd/cache/cache_busyobj.c +++ b/bin/varnishd/cache/cache_busyobj.c @@ -159,7 +159,7 @@ void VBO_DerefBusyObj(struct worker *wrk, struct busyobj **pbo) { struct busyobj *bo; - struct objcore *oc; + struct objcore *oc = NULL; unsigned r; CHECK_OBJ_ORNULL(wrk, WORKER_MAGIC); @@ -167,9 +167,10 @@ VBO_DerefBusyObj(struct worker *wrk, struct busyobj **pbo) bo = *pbo; *pbo = NULL; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); + CHECK_OBJ_ORNULL(bo->fetch_objcore, OBJCORE_MAGIC); CHECK_OBJ_ORNULL(bo->fetch_obj, OBJECT_MAGIC); - if (bo->fetch_obj != NULL) { - oc = bo->fetch_obj->objcore; + if (bo->fetch_objcore != NULL) { + oc = bo->fetch_objcore; CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); CHECK_OBJ_NOTNULL(oc->objhead, OBJHEAD_MAGIC); Lck_Lock(&oc->objhead->mtx); @@ -177,7 +178,6 @@ VBO_DerefBusyObj(struct worker *wrk, struct busyobj **pbo) r = --bo->refcount; Lck_Unlock(&oc->objhead->mtx); } else { - oc = NULL; Lck_Lock(&bo->mtx); assert(bo->refcount > 0); r = --bo->refcount; @@ -190,9 +190,9 @@ VBO_DerefBusyObj(struct worker *wrk, struct busyobj **pbo) VSLb(bo->vsl, SLT_End, "%s", ""); VSL_Flush(bo->vsl, 0); - if (oc != NULL) { + if (bo->fetch_objcore != NULL) { AN(wrk); - (void)HSH_Deref(&wrk->stats, NULL, &bo->fetch_obj); + (void)HSH_Deref(&wrk->stats, bo->fetch_objcore, NULL); } VCL_Rel(&bo->vcl); diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index 441ce2a..1f8ec3d 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -345,6 +345,7 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) AZ(bo->stats); bo->stats = &wrk->stats; + AN(bo->fetch_objcore); obj = STV_NewObject(bo, bo->storage_hint, l, nhttp); if (obj == NULL) { /* diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index d66c3de..442d7db 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -162,6 +162,7 @@ cnt_deliver(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(req->obj->objcore, OBJCORE_MAGIC); + CHECK_OBJ_NOTNULL(req->obj->objcore->objhead, OBJHEAD_MAGIC); CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); assert(req->obj->objcore->refcnt > 0); @@ -288,9 +289,10 @@ cnt_error(struct worker *wrk, struct req *req) AZ(bo->stats); bo->stats = &wrk->stats; bo->fetch_objcore = HSH_Private(wrk); - req->obj = STV_NewObject(bo, + bo->fetch_obj = STV_NewObject(bo, TRANSIENT_STORAGE, cache_param->http_resp_size, (uint16_t)cache_param->http_max_hdr); + req->obj = bo->fetch_obj; bo->stats = NULL; if (req->obj == NULL) { req->doclose = SC_OVERLOAD; @@ -305,7 +307,6 @@ cnt_error(struct worker *wrk, struct req *req) } CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); AZ(req->objcore); - AZ(bo->fetch_objcore); req->obj->vxid = bo->vsl->wid; req->obj->exp.entered = req->t_req; @@ -320,6 +321,9 @@ cnt_error(struct worker *wrk, struct req *req) http_PrintfHeader(h, "Date: %s", date); http_SetHeader(h, "Server: Varnish"); + CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); + HSH_Ref(req->obj->objcore); + if (req->err_reason != NULL) http_PutResponse(h, req->err_reason); else @@ -331,11 +335,12 @@ cnt_error(struct worker *wrk, struct req *req) wrk->handling = VCL_RET_DELIVER; if (wrk->handling == VCL_RET_RESTART) { - HSH_Drop(wrk, &req->obj); VBO_DerefBusyObj(wrk, &req->busyobj); + HSH_Drop(wrk, &req->obj); req->req_step = R_STP_RESTART; return (REQ_FSM_MORE); } + CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); /* We always close when we take this path */ req->doclose = SC_TX_ERROR; @@ -345,8 +350,10 @@ cnt_error(struct worker *wrk, struct req *req) req->err_code = 0; req->err_reason = NULL; http_Teardown(bo->bereq); + CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); VBO_DerefBusyObj(wrk, &req->busyobj); req->req_step = R_STP_DELIVER; + CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); return (REQ_FSM_MORE); } diff --git a/bin/varnishd/storage/stevedore.c b/bin/varnishd/storage/stevedore.c index af14533..5b36c08 100644 --- a/bin/varnishd/storage/stevedore.c +++ b/bin/varnishd/storage/stevedore.c @@ -288,7 +288,6 @@ STV_MkObject(struct stevedore *stv, struct busyobj *bo, bo->stats->n_object++; o->objcore = bo->fetch_objcore; - bo->fetch_objcore = NULL; /* refcnt follows pointer. */ if (!(o->objcore->flags & OC_F_PRIVATE)) BAN_NewObjCore(o->objcore); From phk at varnish-cache.org Tue Sep 3 11:57:28 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 03 Sep 2013 13:57:28 +0200 Subject: [master] ab82163 Propagate BOS_FAILED to the objcore, and ignore OC_F_FAILED objects in HSH_Lookup() Message-ID: commit ab821632f695427357849fd63f36523600916e7a Author: Poul-Henning Kamp Date: Tue Sep 3 11:56:58 2013 +0000 Propagate BOS_FAILED to the objcore, and ignore OC_F_FAILED objects in HSH_Lookup() diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 9b68f79..71bff9c 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -424,6 +424,7 @@ struct objcore { #define OC_F_PRIV (1<<5) /* Stevedore private flag */ #define OC_F_LURK (3<<6) /* Ban-lurker-color */ #define OC_F_PRIVATE (1<<8) +#define OC_F_FAILED (1<<9) unsigned timer_idx; VTAILQ_ENTRY(objcore) list; VTAILQ_ENTRY(objcore) lru_list; diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index 1f8ec3d..d365158 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -118,7 +118,7 @@ vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo) if (wrk->handling == VCL_RET_ABANDON) { if (bo->req != NULL) vbf_release_req(bo); - VBO_setstate(bo, BOS_FAILED); + (void)VFP_Error(bo, "Abandonned in vcl_backend_fetch"); return (F_STP_ABANDON); } assert (wrk->handling == VCL_RET_FETCH); @@ -360,10 +360,8 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) } bo->stats = NULL; if (obj == NULL) { - (void)HSH_Deref(&wrk->stats, bo->fetch_objcore, NULL); - bo->fetch_objcore = NULL; + (void)VFP_Error(bo, "Could not get storage"); VDI_CloseFd(&bo->vbc); - VBO_setstate(bo, BOS_FAILED); return (F_STP_ABANDON); } CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC); @@ -428,12 +426,8 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) assert(bo->refcount >= 1); - if (bo->state == BOS_FAILED) { - /* handle early failures */ - (void)HSH_Deref(&wrk->stats, NULL, &obj); - return (F_STP_ABANDON); - } - VBO_setstate(bo, BOS_FINISHED); + if (bo->state != BOS_FAILED) + VBO_setstate(bo, BOS_FINISHED); VSLb(bo->vsl, SLT_Debug, "YYY REF %d %d", bo->refcount, bo->fetch_obj->objcore->refcnt); VBO_DerefBusyObj(wrk, &bo); // XXX ? @@ -450,6 +444,7 @@ vbf_stp_abandon(struct worker *wrk, struct busyobj *bo) CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); assert(bo->state == BOS_FAILED); + assert(bo->fetch_objcore->flags & OC_F_FAILED); VBO_DerefBusyObj(wrk, &bo); // XXX ? return (F_STP_DONE); } @@ -571,5 +566,8 @@ VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc, return (NULL); } VBO_waitstate(bo, BOS_FETCHING); + if (!bo->do_stream) + VBO_waitstate(bo, BOS_FINISHED); + assert(bo->state != BOS_FAILED || (oc->flags & OC_F_FAILED)); return (bo); } diff --git a/bin/varnishd/cache/cache_fetch_proc.c b/bin/varnishd/cache/cache_fetch_proc.c index 37a2f4d..2871b73 100644 --- a/bin/varnishd/cache/cache_fetch_proc.c +++ b/bin/varnishd/cache/cache_fetch_proc.c @@ -62,6 +62,8 @@ VFP_Error2(struct busyobj *bo, const char *error, const char *more) VSLb(bo->vsl, SLT_FetchError, "%s", error); else VSLb(bo->vsl, SLT_FetchError, "%s: %s", error, more); + if (bo->fetch_objcore != NULL) + HSH_Fail(bo->fetch_objcore); VBO_setstate(bo, BOS_FAILED); } return (-1); diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c index 6fd51f6..ad63438 100644 --- a/bin/varnishd/cache/cache_hash.c +++ b/bin/varnishd/cache/cache_hash.c @@ -401,6 +401,9 @@ HSH_Lookup(struct req *req, struct objcore **ocp, struct objcore **bocp, CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); assert(oc->objhead == oh); + if (oc->flags & OC_F_FAILED) + continue; + if (oc->flags & OC_F_BUSY || oc->busyobj != NULL) { CHECK_OBJ_ORNULL(oc->busyobj, BUSYOBJ_MAGIC); if (req->hash_ignore_busy) @@ -624,6 +627,24 @@ HSH_Drop(struct worker *wrk, struct object **oo) } /*--------------------------------------------------------------------- + * Fail an objcore + */ + +void +HSH_Fail(struct objcore *oc) +{ + struct objhead *oh; + + CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); + oh = oc->objhead; + CHECK_OBJ(oh, OBJHEAD_MAGIC); + + Lck_Lock(&oh->mtx); + oc->flags |= OC_F_FAILED; + Lck_Unlock(&oh->mtx); +} + +/*--------------------------------------------------------------------- * Remove the busyobj from an objcore */ diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 442d7db..f8317b5 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -385,20 +385,18 @@ cnt_fetch(struct worker *wrk, struct req *req) assert(bo->refcount > 0); (void)HTTP1_DiscardReqBody(req); - /* bo->do_stream is not valid until after vcl_backend_response{} */ - if (!bo->do_stream) - VBO_waitstate(bo, BOS_FINISHED); - - if (bo->state == BOS_FAILED) { + if (req->objcore->flags & OC_F_FAILED) { VBO_DerefBusyObj(wrk, &req->busyobj); req->err_code = 503; req->req_step = R_STP_ERROR; + req->objcore = NULL; return (REQ_FSM_MORE); } assert (bo->state >= BOS_FETCHING); req->err_code = bo->err_code; req->obj = bo->fetch_obj; // XXX: recnt ? + req->objcore = NULL; if (bo->state == BOS_FINISHED) VBO_DerefBusyObj(wrk, &req->busyobj); assert(WRW_IsReleased(wrk)); @@ -609,7 +607,6 @@ cnt_miss(struct worker *wrk, struct req *req) AN (req->objcore); req->busyobj = VBF_Fetch(wrk, req, req->objcore, VBF_NORMAL); - req->objcore = NULL; req->req_step = R_STP_FETCH; return (REQ_FSM_MORE); } @@ -634,7 +631,6 @@ XDOT err_pass [label="ERROR",shape=plaintext] static enum req_fsm_nxt cnt_pass(struct worker *wrk, struct req *req) { - struct objcore *oc; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); @@ -654,9 +650,9 @@ cnt_pass(struct worker *wrk, struct req *req) assert (wrk->handling == VCL_RET_FETCH); req->acct_req.pass++; - oc = HSH_Private(wrk); - AN(oc); - req->busyobj = VBF_Fetch(wrk, req, oc, VBF_PASS); + req->objcore = HSH_Private(wrk); + AN(req->objcore); + req->busyobj = VBF_Fetch(wrk, req, req->objcore, VBF_PASS); req->req_step = R_STP_FETCH; return (REQ_FSM_MORE); } diff --git a/bin/varnishd/hash/hash_slinger.h b/bin/varnishd/hash/hash_slinger.h index 79443c7..5d9e91d 100644 --- a/bin/varnishd/hash/hash_slinger.h +++ b/bin/varnishd/hash/hash_slinger.h @@ -108,6 +108,7 @@ struct objhead { #define hoh_head _u.n.u_n_hoh_head }; +void HSH_Fail(struct objcore *); void HSH_Unbusy(struct dstat *, struct objcore *); void HSH_Complete(struct objcore *oc); void HSH_DeleteObjHead(struct dstat *, struct objhead *oh); From phk at varnish-cache.org Tue Sep 3 13:08:21 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 03 Sep 2013 15:08:21 +0200 Subject: [master] c15676c Don't unbusy objects that are not allowed to stream, until they have fetched their body. Message-ID: commit c15676ca7c8c4335b692190f6064a859059fb5f5 Author: Poul-Henning Kamp Date: Tue Sep 3 13:08:02 2013 +0000 Don't unbusy objects that are not allowed to stream, until they have fetched their body. diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index d365158..6982be8 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -413,7 +413,8 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) } AZ(obj->ws_o->overflow); - HSH_Unbusy(&wrk->stats, obj->objcore); + if (bo->do_stream) + HSH_Unbusy(&wrk->stats, obj->objcore); if (bo->vfp == NULL) bo->vfp = &VFP_nop; @@ -422,6 +423,8 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) VBO_setstate(bo, BOS_FETCHING); V1F_fetch_body(wrk, bo); + if (!bo->do_stream) + HSH_Unbusy(&wrk->stats, obj->objcore); HSH_Complete(obj->objcore); assert(bo->refcount >= 1); From phk at varnish-cache.org Tue Sep 3 21:44:50 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 03 Sep 2013 23:44:50 +0200 Subject: [master] 209f797 Tie the busyobj to the objcore. Message-ID: commit 209f7974d31a4d568a133c0f326825e144c8b72f Author: Poul-Henning Kamp Date: Tue Sep 3 21:44:25 2013 +0000 Tie the busyobj to the objcore. diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 71bff9c..c104506 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -635,7 +635,6 @@ struct req { /* The busy objhead we sleep on */ struct objhead *hash_objhead; - struct busyobj *busyobj; /* Built Vary string */ uint8_t *vary_b; @@ -851,7 +850,7 @@ enum vbf_fetch_mode_e { VBF_PASS = 1, VBF_BACKGROUND = 2, }; -struct busyobj *VBF_Fetch(struct worker *wrk, struct req *req, +void VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc, enum vbf_fetch_mode_e); /* cache_fetch_proc.c */ diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index 6982be8..8b806be 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -527,7 +527,7 @@ vbf_fetch_thread(struct worker *wrk, void *priv) /*-------------------------------------------------------------------- */ -struct busyobj * +void VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc, enum vbf_fetch_mode_e mode) { @@ -565,12 +565,11 @@ VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc, vbf_fetch_thread(wrk, bo); if (mode == VBF_BACKGROUND) { VBO_waitstate(bo, BOS_REQ_DONE); - VBO_DerefBusyObj(wrk, &bo); - return (NULL); + } else { + VBO_waitstate(bo, BOS_FETCHING); + if (!bo->do_stream) + VBO_waitstate(bo, BOS_FINISHED); + assert(bo->state != BOS_FAILED || (oc->flags & OC_F_FAILED)); } - VBO_waitstate(bo, BOS_FETCHING); - if (!bo->do_stream) - VBO_waitstate(bo, BOS_FINISHED); - assert(bo->state != BOS_FAILED || (oc->flags & OC_F_FAILED)); - return (bo); + VBO_DerefBusyObj(wrk, &bo); } diff --git a/bin/varnishd/cache/cache_http1_fsm.c b/bin/varnishd/cache/cache_http1_fsm.c index d45abf9..d77c36e 100644 --- a/bin/varnishd/cache/cache_http1_fsm.c +++ b/bin/varnishd/cache/cache_http1_fsm.c @@ -183,7 +183,6 @@ http1_cleanup(struct sess *sp, struct worker *wrk, struct req *req) CHECK_OBJ_ORNULL(req->vcl, VCL_CONF_MAGIC); AZ(req->obj); - AZ(req->busyobj); req->director = NULL; req->restarts = 0; diff --git a/bin/varnishd/cache/cache_panic.c b/bin/varnishd/cache/cache_panic.c index 2d23723..fdd7bb3 100644 --- a/bin/varnishd/cache/cache_panic.c +++ b/bin/varnishd/cache/cache_panic.c @@ -329,11 +329,11 @@ pan_req(const struct req *req) if (VALID_OBJ(req->vcl, VCL_CONF_MAGIC)) pan_vcl(req->vcl); - if (req->busyobj != NULL) - pan_busyobj(req->busyobj); - - if (VALID_OBJ(req->obj, OBJECT_MAGIC)) + if (VALID_OBJ(req->obj, OBJECT_MAGIC)) { + if (req->obj->objcore->busyobj != NULL) + pan_busyobj(req->obj->objcore->busyobj); pan_object(req->obj); + } VSB_printf(pan_vsp, "},\n"); } diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index f8317b5..c918ec1 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -95,7 +95,7 @@ cnt_stream(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - bo = req->busyobj; + bo = req->obj->objcore->busyobj; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); AN(bo->do_stream); @@ -107,7 +107,7 @@ cnt_stream(struct worker *wrk, struct req *req) if (wrk->handling == VCL_RET_RESTART) { assert(req->obj == bo->fetch_obj); req->obj = NULL; - VBO_DerefBusyObj(wrk, &req->busyobj); + VBO_DerefBusyObj(wrk, &bo); AZ(req->obj); http_Teardown(req->resp); req->req_step = R_STP_RESTART; @@ -120,14 +120,14 @@ cnt_stream(struct worker *wrk, struct req *req) if (bo->state == BOS_FAILED) { (void)HSH_Deref(&wrk->stats, NULL, &req->obj); - VBO_DerefBusyObj(wrk, &req->busyobj); + VBO_DerefBusyObj(wrk, &bo); req->err_code = 503; req->req_step = R_STP_ERROR; return (REQ_FSM_MORE); } - VBO_DerefBusyObj(wrk, &req->busyobj); + VBO_DerefBusyObj(wrk, &bo); - AZ(req->busyobj); + AZ(bo); RES_WriteObj(req); @@ -170,11 +170,10 @@ cnt_deliver(struct worker *wrk, struct req *req) req->res_mode = 0; if (!req->disable_esi && req->obj->esidata != NULL) { - AZ(req->busyobj); /* In ESI mode, we can't know the aggregate length */ req->res_mode &= ~RES_LEN; req->res_mode |= RES_ESI; - } else if (req->busyobj == NULL) { + } else if (req->obj->objcore->busyobj == NULL) { req->res_mode |= RES_LEN; } @@ -205,6 +204,7 @@ cnt_deliver(struct worker *wrk, struct req *req) req->doclose = SC_TX_EOF; } } + VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode); req->t_resp = W_TIM_real(wrk); if (!(req->obj->objcore->flags & OC_F_PRIVATE)) { @@ -220,21 +220,16 @@ cnt_deliver(struct worker *wrk, struct req *req) VCL_deliver_method(req->vcl, wrk, req, NULL, req->http->ws); + while (req->obj->objcore->busyobj) { + VSLb(req->vsl, SLT_Debug, "HERE %s %d", __func__, __LINE__); + (void)usleep(10000); + } + + /* Stop the insanity before it turns "Hotel California" on us */ if (req->restarts >= cache_param->max_restarts) wrk->handling = VCL_RET_DELIVER; - if (req->busyobj != NULL) { - /* Don't stream if already finished */ - if (req->busyobj->state != BOS_FINISHED) { - AN(req->busyobj->do_stream); - req->req_step = R_STP_STREAM; - return (REQ_FSM_MORE); - } - VBO_DerefBusyObj(wrk, &req->busyobj); - } - AZ(req->busyobj); - if (wrk->handling == VCL_RET_RESTART) { (void)HSH_Deref(&wrk->stats, NULL, &req->obj); AZ(req->obj); @@ -281,11 +276,9 @@ cnt_error(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(req, REQ_MAGIC); AZ(req->objcore); AZ(req->obj); - AZ(req->busyobj); req->acct_req.error++; bo = VBO_GetBusyObj(wrk, req); - req->busyobj = bo; AZ(bo->stats); bo->stats = &wrk->stats; bo->fetch_objcore = HSH_Private(wrk); @@ -301,8 +294,7 @@ cnt_error(struct worker *wrk, struct req *req) bo->fetch_objcore = NULL; http_Teardown(bo->beresp); http_Teardown(bo->bereq); - VBO_DerefBusyObj(wrk, &req->busyobj); - AZ(req->busyobj); + VBO_DerefBusyObj(wrk, &bo); return (REQ_FSM_DONE); } CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); @@ -335,7 +327,7 @@ cnt_error(struct worker *wrk, struct req *req) wrk->handling = VCL_RET_DELIVER; if (wrk->handling == VCL_RET_RESTART) { - VBO_DerefBusyObj(wrk, &req->busyobj); + VBO_DerefBusyObj(wrk, &bo); HSH_Drop(wrk, &req->obj); req->req_step = R_STP_RESTART; return (REQ_FSM_MORE); @@ -351,7 +343,7 @@ cnt_error(struct worker *wrk, struct req *req) req->err_reason = NULL; http_Teardown(bo->bereq); CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); - VBO_DerefBusyObj(wrk, &req->busyobj); + VBO_DerefBusyObj(wrk, &bo); req->req_step = R_STP_DELIVER; CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); return (REQ_FSM_MORE); @@ -374,31 +366,26 @@ DOT fetch:err:s -> vcl_error static enum req_fsm_nxt cnt_fetch(struct worker *wrk, struct req *req) { - struct busyobj *bo; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - bo = req->busyobj; - CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); req->acct_req.fetch++; - assert(bo->refcount > 0); + //assert(bo->refcount > 0); (void)HTTP1_DiscardReqBody(req); if (req->objcore->flags & OC_F_FAILED) { - VBO_DerefBusyObj(wrk, &req->busyobj); req->err_code = 503; req->req_step = R_STP_ERROR; req->objcore = NULL; return (REQ_FSM_MORE); } - assert (bo->state >= BOS_FETCHING); - req->err_code = bo->err_code; - req->obj = bo->fetch_obj; // XXX: recnt ? + //assert (bo->state >= BOS_FETCHING); + req->obj = oc_getobj(&wrk->stats, req->objcore); + //assert(req->obj == bo->fetch_obj); req->objcore = NULL; - if (bo->state == BOS_FINISHED) - VBO_DerefBusyObj(wrk, &req->busyobj); + req->err_code = req->obj->response; assert(WRW_IsReleased(wrk)); req->req_step = R_STP_DELIVER; return (REQ_FSM_MORE); @@ -445,7 +432,6 @@ cnt_lookup(struct worker *wrk, struct req *req) AZ(req->objcore); CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); - AZ(req->busyobj); VRY_Prep(req); @@ -486,7 +472,6 @@ cnt_lookup(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); AZ (oc->flags & OC_F_BUSY); AZ(req->objcore); - AZ(req->busyobj); if (oc->flags & OC_F_PASS) { /* Found a hit-for-pass */ @@ -513,7 +498,7 @@ cnt_lookup(struct worker *wrk, struct req *req) switch (wrk->handling) { case VCL_RET_DELIVER: if (boc != NULL) { - AZ(VBF_Fetch(wrk, req, boc, VBF_BACKGROUND)); + VBF_Fetch(wrk, req, boc, VBF_BACKGROUND); } else { (void)HTTP1_DiscardReqBody(req);// XXX: handle err } @@ -575,7 +560,6 @@ cnt_miss(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC); AZ(req->obj); - AZ(req->busyobj); VCL_miss_method(req->vcl, wrk, req, NULL, req->http->ws); switch (wrk->handling) { @@ -606,7 +590,7 @@ cnt_miss(struct worker *wrk, struct req *req) wrk->stats.cache_miss++; AN (req->objcore); - req->busyobj = VBF_Fetch(wrk, req, req->objcore, VBF_NORMAL); + VBF_Fetch(wrk, req, req->objcore, VBF_NORMAL); req->req_step = R_STP_FETCH; return (REQ_FSM_MORE); } @@ -637,7 +621,6 @@ cnt_pass(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); AZ(req->objcore); AZ(req->obj); - AZ(req->busyobj); VCL_pass_method(req->vcl, wrk, req, NULL, req->http->ws); if (wrk->handling == VCL_RET_ERROR) { @@ -652,7 +635,7 @@ cnt_pass(struct worker *wrk, struct req *req) req->objcore = HSH_Private(wrk); AN(req->objcore); - req->busyobj = VBF_Fetch(wrk, req, req->objcore, VBF_PASS); + VBF_Fetch(wrk, req, req->objcore, VBF_PASS); req->req_step = R_STP_FETCH; return (REQ_FSM_MORE); } @@ -683,7 +666,6 @@ cnt_pipe(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); - AZ(req->busyobj); req->acct_req.pipe++; bo = VBO_GetBusyObj(wrk, req); @@ -769,7 +751,6 @@ cnt_recv(struct worker *wrk, struct req *req) AZ(req->objcore); AZ(req->obj); AZ(req->objcore); - AZ(req->busyobj); VSLb(req->vsl, SLT_ReqStart, "%s %s", req->sp->addr, req->sp->port); @@ -862,7 +843,6 @@ cnt_purge(struct worker *wrk, struct req *req) AZ(req->objcore); CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); - AZ(req->busyobj); VRY_Prep(req); From phk at varnish-cache.org Wed Sep 4 06:41:28 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 04 Sep 2013 08:41:28 +0200 Subject: [master] 129be2f Various polish Message-ID: commit 129be2f9a9dd213d977edd7002432dcad1348e30 Author: Poul-Henning Kamp Date: Wed Sep 4 06:41:19 2013 +0000 Various polish diff --git a/bin/varnishd/cache/cache_ban.c b/bin/varnishd/cache/cache_ban.c index 1229dfb..dbad851 100644 --- a/bin/varnishd/cache/cache_ban.c +++ b/bin/varnishd/cache/cache_ban.c @@ -1073,7 +1073,7 @@ ban_lurker_work(struct worker *wrk, struct vsl_log *vsl) if (DO_DEBUG(DBG_LURKER)) VSLb(vsl, SLT_Debug, "lurker done: %p %u %u", oc, oc->flags & OC_F_LURK, pass); - (void)HSH_Deref(&wrk->stats, NULL, &o); + (void)HSH_DerefObj(&wrk->stats, &o); VTIM_sleep(cache_param->ban_lurker_sleep); } Lck_AssertHeld(&ban_mtx); diff --git a/bin/varnishd/cache/cache_busyobj.c b/bin/varnishd/cache/cache_busyobj.c index 4b6c37f..063c49c 100644 --- a/bin/varnishd/cache/cache_busyobj.c +++ b/bin/varnishd/cache/cache_busyobj.c @@ -192,7 +192,7 @@ VBO_DerefBusyObj(struct worker *wrk, struct busyobj **pbo) if (bo->fetch_objcore != NULL) { AN(wrk); - (void)HSH_Deref(&wrk->stats, bo->fetch_objcore, NULL); + (void)HSH_DerefObjCore(&wrk->stats, &bo->fetch_objcore); } VCL_Rel(&bo->vcl); diff --git a/bin/varnishd/cache/cache_expire.c b/bin/varnishd/cache/cache_expire.c index 2271949..090a209 100644 --- a/bin/varnishd/cache/cache_expire.c +++ b/bin/varnishd/cache/cache_expire.c @@ -411,7 +411,7 @@ exp_timer(struct worker *wrk, void *priv) VSLb(&vsl, SLT_ExpKill, "%u %.0f", oc_getxid(&wrk->stats, oc) & VSL_IDENTMASK, EXP_Ttl(NULL, o) - t); - (void)HSH_Deref(&wrk->stats, oc, NULL); + (void)HSH_DerefObjCore(&wrk->stats, &oc); } NEEDLESS_RETURN(NULL); } @@ -457,7 +457,7 @@ EXP_NukeOne(struct busyobj *bo, struct lru *lru) /* XXX: bad idea for -spersistent */ VSLb(bo->vsl, SLT_ExpKill, "%u LRU", oc_getxid(bo->stats, oc) & VSL_IDENTMASK); - (void)HSH_Deref(bo->stats, oc, NULL); + (void)HSH_DerefObjCore(bo->stats, &oc); return (1); } @@ -513,7 +513,7 @@ EXP_NukeLRU(struct worker *wrk, struct vsl_log *vsl, struct lru *lru) oc_getxid(&wrk->stats, oc) & VSL_IDENTMASK, EXP_Ttl(NULL, o) - t); EXP_Set_ttl(&o->exp, 0.); - (void)HSH_Deref(&wrk->stats, oc, NULL); + (void)HSH_DerefObjCore(&wrk->stats, &oc); } Lck_Lock(&lru->mtx); diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c index ad63438..46ec3ba 100644 --- a/bin/varnishd/cache/cache_hash.c +++ b/bin/varnishd/cache/cache_hash.c @@ -605,7 +605,7 @@ HSH_Purge(struct worker *wrk, struct objhead *oh, double ttl, double grace) o->exp.ttl = ttl; o->exp.grace = grace; EXP_Rearm(o); - (void)HSH_Deref(&wrk->stats, NULL, &o); + (void)HSH_DerefObj(&wrk->stats, &o); } WS_Release(wrk->aws, 0); } @@ -623,7 +623,7 @@ HSH_Drop(struct worker *wrk, struct object **oo) AN(oo); CHECK_OBJ_NOTNULL(*oo, OBJECT_MAGIC); (*oo)->exp.ttl = -1.; - AZ(HSH_Deref(&wrk->stats, NULL, oo)); + AZ(HSH_DerefObj(&wrk->stats, oo)); } /*--------------------------------------------------------------------- @@ -727,21 +727,30 @@ HSH_Ref(struct objcore *oc) */ int -HSH_Deref(struct dstat *ds, struct objcore *oc, struct object **oo) +HSH_DerefObj(struct dstat *ds, struct object **oo) { - struct object *o = NULL; + struct object *o; + struct objcore *oc; + + AN(oo); + o = *oo; + *oo = NULL; + + CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC); + oc = o->objcore; + return (HSH_DerefObjCore(ds, &oc)); +} + +int +HSH_DerefObjCore(struct dstat *ds, struct objcore **ocp) +{ + struct objcore *oc; struct objhead *oh; unsigned r; - /* Only one arg at a time */ - assert(oc == NULL || oo == NULL); - - if (oo != NULL) { - o = *oo; - *oo = NULL; - CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC); - oc = o->objcore; - } + AN(ocp); + oc = *ocp; + *ocp = NULL; CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); assert(oc->refcnt > 0); diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index c918ec1..5fc5171 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -119,7 +119,7 @@ cnt_stream(struct worker *wrk, struct req *req) assert(bo->state >= BOS_FINISHED); if (bo->state == BOS_FAILED) { - (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + (void)HSH_DerefObj(&wrk->stats, &req->obj); VBO_DerefBusyObj(wrk, &bo); req->err_code = 503; req->req_step = R_STP_ERROR; @@ -136,7 +136,7 @@ cnt_stream(struct worker *wrk, struct req *req) STV_Freestore(req->obj); assert(WRW_IsReleased(wrk)); - (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + (void)HSH_DerefObj(&wrk->stats, &req->obj); http_Teardown(req->resp); return (REQ_FSM_DONE); } @@ -164,6 +164,7 @@ cnt_deliver(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(req->obj->objcore, OBJCORE_MAGIC); CHECK_OBJ_NOTNULL(req->obj->objcore->objhead, OBJHEAD_MAGIC); CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); + assert(WRW_IsReleased(wrk)); assert(req->obj->objcore->refcnt > 0); @@ -231,7 +232,7 @@ cnt_deliver(struct worker *wrk, struct req *req) wrk->handling = VCL_RET_DELIVER; if (wrk->handling == VCL_RET_RESTART) { - (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + (void)HSH_DerefObj(&wrk->stats, &req->obj); AZ(req->obj); http_Teardown(req->resp); req->req_step = R_STP_RESTART; @@ -247,7 +248,7 @@ cnt_deliver(struct worker *wrk, struct req *req) assert(WRW_IsReleased(wrk)); VSLb(req->vsl, SLT_Debug, "XXX REF %d", req->obj->objcore->refcnt); - (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + (void)HSH_DerefObj(&wrk->stats, &req->obj); http_Teardown(req->resp); return (REQ_FSM_DONE); } @@ -290,7 +291,7 @@ cnt_error(struct worker *wrk, struct req *req) if (req->obj == NULL) { req->doclose = SC_OVERLOAD; req->director = NULL; - AZ(HSH_Deref(&wrk->stats, bo->fetch_objcore, NULL)); + AZ(HSH_DerefObjCore(&wrk->stats, &bo->fetch_objcore)); bo->fetch_objcore = NULL; http_Teardown(bo->beresp); http_Teardown(bo->bereq); @@ -369,24 +370,22 @@ cnt_fetch(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + AZ(req->obj); req->acct_req.fetch++; - //assert(bo->refcount > 0); (void)HTTP1_DiscardReqBody(req); if (req->objcore->flags & OC_F_FAILED) { req->err_code = 503; req->req_step = R_STP_ERROR; + //XXX ? AZ(HSH_DerefObjCore(&wrk->stats, &req->objcore)); req->objcore = NULL; return (REQ_FSM_MORE); } - //assert (bo->state >= BOS_FETCHING); req->obj = oc_getobj(&wrk->stats, req->objcore); - //assert(req->obj == bo->fetch_obj); req->objcore = NULL; req->err_code = req->obj->response; - assert(WRW_IsReleased(wrk)); req->req_step = R_STP_DELIVER; return (REQ_FSM_MORE); } @@ -477,7 +476,7 @@ cnt_lookup(struct worker *wrk, struct req *req) /* Found a hit-for-pass */ VSLb(req->vsl, SLT_Debug, "XXXX HIT-FOR-PASS"); AZ(boc); - (void)HSH_Deref(&wrk->stats, oc, NULL); + (void)HSH_DerefObjCore(&wrk->stats, &oc); req->objcore = NULL; wrk->stats.cache_hitpass++; req->req_step = R_STP_PASS; @@ -506,7 +505,7 @@ cnt_lookup(struct worker *wrk, struct req *req) req->req_step = R_STP_DELIVER; return (REQ_FSM_MORE); case VCL_RET_FETCH: - (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + (void)HSH_DerefObj(&wrk->stats, &req->obj); req->objcore = boc; req->req_step = R_STP_MISS; return (REQ_FSM_MORE); @@ -525,11 +524,11 @@ cnt_lookup(struct worker *wrk, struct req *req) } /* Drop our object, we won't need it */ - (void)HSH_Deref(&wrk->stats, NULL, &req->obj); + (void)HSH_DerefObj(&wrk->stats, &req->obj); req->objcore = NULL; if (boc != NULL) { - (void)HSH_Deref(&wrk->stats, boc, NULL); + (void)HSH_DerefObjCore(&wrk->stats, &boc); free(req->vary_b); req->vary_b = NULL; } @@ -563,35 +562,25 @@ cnt_miss(struct worker *wrk, struct req *req) VCL_miss_method(req->vcl, wrk, req, NULL, req->http->ws); switch (wrk->handling) { + case VCL_RET_FETCH: + wrk->stats.cache_miss++; + VBF_Fetch(wrk, req, req->objcore, VBF_NORMAL); + req->req_step = R_STP_FETCH; + return (REQ_FSM_MORE); case VCL_RET_ERROR: - free(req->vary_b); - AZ(HSH_Deref(&wrk->stats, req->objcore, NULL)); - req->objcore = NULL; req->req_step = R_STP_ERROR; - return (REQ_FSM_MORE); + break; case VCL_RET_RESTART: - free(req->vary_b); - AZ(HSH_Deref(&wrk->stats, req->objcore, NULL)); - req->objcore = NULL; req->req_step = R_STP_RESTART; - return (REQ_FSM_MORE); + break; case VCL_RET_PASS: - free(req->vary_b); - AZ(HSH_Deref(&wrk->stats, req->objcore, NULL)); - req->objcore = NULL; req->req_step = R_STP_PASS; - return (REQ_FSM_MORE); - case VCL_RET_FETCH: break; default: - WRONG("wrong return from vcl_miss{}"); + WRONG("Illegal return from vcl_miss{}"); } - - wrk->stats.cache_miss++; - - AN (req->objcore); - VBF_Fetch(wrk, req, req->objcore, VBF_NORMAL); - req->req_step = R_STP_FETCH; + free(req->vary_b); + AZ(HSH_DerefObjCore(&wrk->stats, &req->objcore)); return (REQ_FSM_MORE); } @@ -623,20 +612,23 @@ cnt_pass(struct worker *wrk, struct req *req) AZ(req->obj); VCL_pass_method(req->vcl, wrk, req, NULL, req->http->ws); - if (wrk->handling == VCL_RET_ERROR) { + switch (wrk->handling) { + case VCL_RET_ERROR: req->req_step = R_STP_ERROR; - return (REQ_FSM_MORE); - } - if (wrk->handling == VCL_RET_RESTART) { - INCOMPL(); + break; + case VCL_RET_RESTART: + req->req_step = R_STP_RESTART; + break; + case VCL_RET_FETCH: + req->acct_req.pass++; + req->objcore = HSH_Private(wrk); + CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC); + VBF_Fetch(wrk, req, req->objcore, VBF_PASS); + req->req_step = R_STP_FETCH; + break; + default: + WRONG("Illegal return from cnt_pass{}"); } - assert (wrk->handling == VCL_RET_FETCH); - req->acct_req.pass++; - - req->objcore = HSH_Private(wrk); - AN(req->objcore); - VBF_Fetch(wrk, req, req->objcore, VBF_PASS); - req->req_step = R_STP_FETCH; return (REQ_FSM_MORE); } @@ -807,13 +799,15 @@ cnt_recv(struct worker *wrk, struct req *req) req->req_step = R_STP_LOOKUP; return (REQ_FSM_MORE); case VCL_RET_PIPE: - if (req->esi_level > 0) { - /* XXX: VSL something */ - INCOMPL(); - return (REQ_FSM_DONE); + if (req->esi_level == 0) { + req->req_step = R_STP_PIPE; + return (REQ_FSM_MORE); } - req->req_step = R_STP_PIPE; - return (REQ_FSM_MORE); + VSLb(req->vsl, SLT_VCL_Error, + "vcl_recv{} returns pipe for ESI included object." + " Doing pass."); + req->req_step = R_STP_PASS; + return (REQ_FSM_DONE); case VCL_RET_PASS: req->req_step = R_STP_PASS; return (REQ_FSM_MORE); @@ -821,7 +815,7 @@ cnt_recv(struct worker *wrk, struct req *req) req->req_step = R_STP_ERROR; return (REQ_FSM_MORE); default: - WRONG("Illegal action in vcl_recv{}"); + WRONG("Illegal return from vcl_recv{}"); } } @@ -855,7 +849,7 @@ cnt_purge(struct worker *wrk, struct req *req) HSH_Purge(wrk, boc->objhead, 0, 0); - AZ(HSH_Deref(&wrk->stats, boc, NULL)); + AZ(HSH_DerefObjCore(&wrk->stats, &boc)); VCL_purge_method(req->vcl, wrk, req, NULL, req->http->ws); req->req_step = R_STP_ERROR; diff --git a/bin/varnishd/hash/hash_slinger.h b/bin/varnishd/hash/hash_slinger.h index 5d9e91d..152eebd 100644 --- a/bin/varnishd/hash/hash_slinger.h +++ b/bin/varnishd/hash/hash_slinger.h @@ -113,7 +113,8 @@ void HSH_Unbusy(struct dstat *, struct objcore *); void HSH_Complete(struct objcore *oc); void HSH_DeleteObjHead(struct dstat *, struct objhead *oh); int HSH_DerefObjHead(struct dstat *, struct objhead **poh); -int HSH_Deref(struct dstat *, struct objcore *oc, struct object **o); +int HSH_DerefObjCore(struct dstat *, struct objcore **ocp); +int HSH_DerefObj(struct dstat *, struct object **o); #endif /* VARNISH_CACHE_CHILD */ extern const struct hash_slinger hsl_slinger; From phk at varnish-cache.org Wed Sep 4 06:52:10 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 04 Sep 2013 08:52:10 +0200 Subject: [master] 164378c Fix and test a refcount leak Message-ID: commit 164378c5cd35ab4eddf587f91ef1a977454029ef Author: Poul-Henning Kamp Date: Wed Sep 4 06:51:58 2013 +0000 Fix and test a refcount leak diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 5fc5171..ca47bf0 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -370,6 +370,7 @@ cnt_fetch(struct worker *wrk, struct req *req) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC); AZ(req->obj); req->acct_req.fetch++; @@ -378,7 +379,7 @@ cnt_fetch(struct worker *wrk, struct req *req) if (req->objcore->flags & OC_F_FAILED) { req->err_code = 503; req->req_step = R_STP_ERROR; - //XXX ? AZ(HSH_DerefObjCore(&wrk->stats, &req->objcore)); + (void)HSH_DerefObjCore(&wrk->stats, &req->objcore); req->objcore = NULL; return (REQ_FSM_MORE); } diff --git a/bin/varnishtest/tests/b00020.vtc b/bin/varnishtest/tests/b00020.vtc index 6b6943d..dbe6831 100644 --- a/bin/varnishtest/tests/b00020.vtc +++ b/bin/varnishtest/tests/b00020.vtc @@ -22,6 +22,9 @@ client c1 { expect resp.status == 503 } -run +varnish v1 -expect n_object == 0 +varnish v1 -expect n_objectcore == 0 + server s1 { rxreq send "HTTP/1.1 200 Ok\r\nConnection: close\r\n\r\n" @@ -36,3 +39,7 @@ client c1 { rxresp expect resp.status == 200 } -run + +varnish v1 -expect n_object == 1 +varnish v1 -expect n_objectcore == 1 + From phk at varnish-cache.org Wed Sep 4 08:53:22 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 04 Sep 2013 10:53:22 +0200 Subject: [master] 1764f13 Split resp.* construction so that version independent stuff goes into req_fsm.c::cnt_deliver{} Message-ID: commit 1764f13a7b74d492107d031f34a6935c712ae3da Author: Poul-Henning Kamp Date: Wed Sep 4 08:52:34 2013 +0000 Split resp.* construction so that version independent stuff goes into req_fsm.c::cnt_deliver{} diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index ca47bf0..bfde6f7 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -157,6 +157,7 @@ DOT deliver:stream:s -> stream [style=bold,color=blue] static enum req_fsm_nxt cnt_deliver(struct worker *wrk, struct req *req) { + char time_str[30]; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); @@ -216,11 +217,34 @@ cnt_deliver(struct worker *wrk, struct req *req) if (!cache_param->obj_readonly) req->obj->last_use = req->t_resp; /* XXX: locking ? */ } + HTTP_Setup(req->resp, req->ws, req->vsl, HTTP_Resp); - RES_BuildHttp(req); + + http_ClrHeader(req->resp); + http_FilterResp(req->obj->http, req->resp, 0); + + http_Unset(req->resp, H_Date); + VTIM_format(VTIM_real(), time_str); + http_PrintfHeader(req->resp, "Date: %s", time_str); + + if (req->wrk->stats.cache_hit) + http_PrintfHeader(req->resp, + "X-Varnish: %u %u", req->vsl->wid & VSL_IDENTMASK, + req->obj->vxid & VSL_IDENTMASK); + else + http_PrintfHeader(req->resp, + "X-Varnish: %u", req->vsl->wid & VSL_IDENTMASK); + + http_PrintfHeader(req->resp, "Age: %.0f", + req->obj->exp.age + req->t_resp - req->obj->exp.entered); + + http_SetHeader(req->resp, "Via: 1.1 varnish"); + VCL_deliver_method(req->vcl, wrk, req, NULL, req->http->ws); + RES_BuildHttp(req); + while (req->obj->objcore->busyobj) { VSLb(req->vsl, SLT_Debug, "HERE %s %d", __func__, __LINE__); (void)usleep(10000); diff --git a/bin/varnishd/cache/cache_response.c b/bin/varnishd/cache/cache_response.c index 5e9f997..0dee670 100644 --- a/bin/varnishd/cache/cache_response.c +++ b/bin/varnishd/cache/cache_response.c @@ -32,7 +32,6 @@ #include "cache.h" #include "vct.h" -#include "vtim.h" /*--------------------------------------------------------------------*/ @@ -105,14 +104,10 @@ res_dorange(const struct req *req, const char *r, ssize_t *plow, ssize_t *phigh) void RES_BuildHttp(struct req *req) { - char time_str[30]; CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); - http_ClrHeader(req->resp); - http_FilterResp(req->obj->http, req->resp, 0); - if (!(req->res_mode & RES_LEN)) { http_Unset(req->resp, H_Content_Length); } else if (cache_param->http_range_support) { @@ -133,21 +128,6 @@ RES_BuildHttp(struct req *req) } else if (req->res_mode & RES_CHUNKED) http_SetHeader(req->resp, "Transfer-Encoding: chunked"); - http_Unset(req->resp, H_Date); - VTIM_format(VTIM_real(), time_str); - http_PrintfHeader(req->resp, "Date: %s", time_str); - - if (req->wrk->stats.cache_hit) - http_PrintfHeader(req->resp, - "X-Varnish: %u %u", req->vsl->wid & VSL_IDENTMASK, - req->obj->vxid & VSL_IDENTMASK); - else - http_PrintfHeader(req->resp, - "X-Varnish: %u", req->vsl->wid & VSL_IDENTMASK); - http_PrintfHeader(req->resp, "Age: %.0f", - req->obj->exp.age + req->t_resp - - req->obj->exp.entered); - http_SetHeader(req->resp, "Via: 1.1 varnish"); http_PrintfHeader(req->resp, "Connection: %s", req->doclose ? "close" : "keep-alive"); } From phk at varnish-cache.org Wed Sep 4 13:14:24 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 04 Sep 2013 15:14:24 +0200 Subject: [master] 0ea8328 Further split the "how" from the "what" of response delivery. Message-ID: commit 0ea83286f2aca91d4f8f33c4589dd3e70aebfac7 Author: Poul-Henning Kamp Date: Wed Sep 4 13:12:45 2013 +0000 Further split the "how" from the "what" of response delivery. Here be dragons. For instance that if a HEAD is passed, we should let the Content-Length: unmolested through, whereas normally C-L is a property of the protocol delivery of the HTTP response. diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index 8b806be..4c926e9 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -306,8 +306,7 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) if (bo->htc.body_status == BS_NONE) bo->do_stream = 0; - l = http_EstimateWS(bo->beresp, - bo->uncacheable ? HTTPH_R_PASS : HTTPH_A_INS, &nhttp); + l = 0; /* Create Vary instructions */ if (!(bo->fetch_objcore->flags & OC_F_PRIVATE)) { @@ -331,18 +330,15 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) AZ(vary); } + l += http_EstimateWS(bo->beresp, + bo->uncacheable ? HTTPH_R_PASS : HTTPH_A_INS, &nhttp); + if (bo->uncacheable) bo->fetch_objcore->flags |= OC_F_PASS; if (bo->exp.ttl < cache_param->shortlived || bo->uncacheable == 1) bo->storage_hint = TRANSIENT_STORAGE; - /* - * Space for producing a Content-Length: header including padding - * A billion gigabytes is enough for anybody. - */ - l += strlen("Content-Length: XxxXxxXxxXxxXxxXxx") + sizeof(void *); - AZ(bo->stats); bo->stats = &wrk->stats; AN(bo->fetch_objcore); diff --git a/bin/varnishd/cache/cache_http1_fetch.c b/bin/varnishd/cache/cache_http1_fetch.c index 01511e8..e8dbdaa 100644 --- a/bin/varnishd/cache/cache_http1_fetch.c +++ b/bin/varnishd/cache/cache_http1_fetch.c @@ -311,7 +311,6 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo) { int cls; struct storage *st; - int mklen; ssize_t cl; struct http_conn *htc; struct object *obj; @@ -342,10 +341,8 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo) cls = bo->should_close; switch (htc->body_status) { case BS_NONE: - mklen = 0; break; case BS_ZERO: - mklen = 1; break; case BS_LENGTH: cl = vbf_fetch_number(bo->h_content_length, 10); @@ -353,7 +350,6 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo) bo->vfp->begin(bo, cl); if (bo->state == BOS_FETCHING && cl > 0) cls |= vbf_fetch_straight(bo, htc, cl); - mklen = 1; if (bo->vfp->end(bo)) assert(bo->state == BOS_FAILED); break; @@ -361,7 +357,6 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo) bo->vfp->begin(bo, cl > 0 ? cl : 0); if (bo->state == BOS_FETCHING) cls |= vbf_fetch_chunked(bo, htc); - mklen = 1; if (bo->vfp->end(bo)) assert(bo->state == BOS_FAILED); break; @@ -369,17 +364,14 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo) bo->vfp->begin(bo, cl > 0 ? cl : 0); if (bo->state == BOS_FETCHING) vbf_fetch_eof(bo, htc); - mklen = 1; cls = 1; if (bo->vfp->end(bo)) assert(bo->state == BOS_FAILED); break; case BS_ERROR: cls |= VFP_Error(bo, "error incompatible Transfer-Encoding"); - mklen = 0; break; default: - mklen = 0; INCOMPL(); } AZ(bo->vgz_rx); @@ -401,9 +393,8 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo) bo->vfp = NULL; - VSLb(bo->vsl, SLT_Fetch_Body, "%u(%s) cls %d mklen %d", - htc->body_status, body_status_2str(htc->body_status), - cls, mklen); + VSLb(bo->vsl, SLT_Fetch_Body, "%u(%s) cls %d", + htc->body_status, body_status_2str(htc->body_status), cls); http_Teardown(bo->bereq); http_Teardown(bo->beresp); @@ -440,12 +431,6 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo) else assert(uu == obj->len); } - - if (mklen > 0) { - http_Unset(obj->http, H_Content_Length); - http_PrintfHeader(obj->http, - "Content-Length: %zd", obj->len); - } } bo->stats = NULL; } diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index bfde6f7..9ed176e 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -169,45 +169,6 @@ cnt_deliver(struct worker *wrk, struct req *req) assert(req->obj->objcore->refcnt > 0); - req->res_mode = 0; - - if (!req->disable_esi && req->obj->esidata != NULL) { - /* In ESI mode, we can't know the aggregate length */ - req->res_mode &= ~RES_LEN; - req->res_mode |= RES_ESI; - } else if (req->obj->objcore->busyobj == NULL) { - req->res_mode |= RES_LEN; - } - - if (req->esi_level > 0) { - /* Included ESI object, always CHUNKED or EOF */ - req->res_mode &= ~RES_LEN; - req->res_mode |= RES_ESI_CHILD; - } - - if (cache_param->http_gzip_support && req->obj->gziped && - !RFC2616_Req_Gzip(req->http)) { - /* - * We don't know what it uncompresses to - * XXX: we could cache that - */ - req->res_mode &= ~RES_LEN; - req->res_mode |= RES_GUNZIP; - } - - if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) { - /* We havn't chosen yet, do so */ - if (!req->wantbody) { - /* Nothing */ - } else if (req->http->protover >= 11) { - req->res_mode |= RES_CHUNKED; - } else { - req->res_mode |= RES_EOF; - req->doclose = SC_TX_EOF; - } - } - VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode); - req->t_resp = W_TIM_real(wrk); if (!(req->obj->objcore->flags & OC_F_PRIVATE)) { if ((req->t_resp - req->obj->last_lru) > @@ -224,7 +185,7 @@ cnt_deliver(struct worker *wrk, struct req *req) http_FilterResp(req->obj->http, req->resp, 0); http_Unset(req->resp, H_Date); - VTIM_format(VTIM_real(), time_str); + VTIM_format(req->t_resp, time_str); http_PrintfHeader(req->resp, "Date: %s", time_str); if (req->wrk->stats.cache_hit) @@ -239,17 +200,15 @@ cnt_deliver(struct worker *wrk, struct req *req) req->obj->exp.age + req->t_resp - req->obj->exp.entered); http_SetHeader(req->resp, "Via: 1.1 varnish"); - VCL_deliver_method(req->vcl, wrk, req, NULL, req->http->ws); - RES_BuildHttp(req); - while (req->obj->objcore->busyobj) { VSLb(req->vsl, SLT_Debug, "HERE %s %d", __func__, __LINE__); (void)usleep(10000); } + RES_BuildHttp(req); /* Stop the insanity before it turns "Hotel California" on us */ if (req->restarts >= cache_param->max_restarts) diff --git a/bin/varnishd/cache/cache_response.c b/bin/varnishd/cache/cache_response.c index 0dee670..c56932e 100644 --- a/bin/varnishd/cache/cache_response.c +++ b/bin/varnishd/cache/cache_response.c @@ -108,13 +108,57 @@ RES_BuildHttp(struct req *req) CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); - if (!(req->res_mode & RES_LEN)) { - http_Unset(req->resp, H_Content_Length); - } else if (cache_param->http_range_support) { - /* We only accept ranges if we know the length */ - http_SetHeader(req->resp, "Accept-Ranges: bytes"); + req->res_mode = 0; + + if (!req->disable_esi && req->obj->esidata != NULL) { + /* In ESI mode, we can't know the aggregate length */ + req->res_mode &= ~RES_LEN; + req->res_mode |= RES_ESI; + } else if (req->obj->objcore->busyobj == NULL) { + /* XXX: Not happy with this convoluted test */ + req->res_mode |= RES_LEN; + if (!(req->obj->objcore->flags & OC_F_PASS) || + req->obj->len != 0) { + http_Unset(req->resp, H_Content_Length); + http_PrintfHeader(req->resp, + "Content-Length: %zd", req->obj->len); + } + if (cache_param->http_range_support) + http_SetHeader(req->resp, "Accept-Ranges: bytes"); + } + + if (req->esi_level > 0) { + /* Included ESI object, always CHUNKED or EOF */ + req->res_mode &= ~RES_LEN; + req->res_mode |= RES_ESI_CHILD; + } + + if (cache_param->http_gzip_support && req->obj->gziped && + !RFC2616_Req_Gzip(req->http)) { + /* + * We don't know what it uncompresses to + * XXX: we could cache that + */ + req->res_mode &= ~RES_LEN; + req->res_mode |= RES_GUNZIP; } + if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) { + /* We havn't chosen yet, do so */ + if (!req->wantbody) { + /* Nothing */ + } else if (req->http->protover >= 11) { + req->res_mode |= RES_CHUNKED; + } else { + req->res_mode |= RES_EOF; + req->doclose = SC_TX_EOF; + } + } + VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode); + + if (!(req->res_mode & RES_LEN)) + http_Unset(req->resp, H_Content_Length); + if (req->res_mode & RES_GUNZIP) http_Unset(req->resp, H_Content_Encoding); diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c index de2cf78..36b2a43 100644 --- a/bin/varnishd/cache/cache_vrt.c +++ b/bin/varnishd/cache/cache_vrt.c @@ -419,8 +419,6 @@ VRT_synth_page(const struct vrt_ctx *ctx, unsigned flags, const char *str, ...) va_end(ap); SMS_Finish(ctx->req->obj); http_Unset(ctx->req->obj->http, H_Content_Length); - http_PrintfHeader(ctx->req->obj->http, - "Content-Length: %zd", ctx->req->obj->len); } /*--------------------------------------------------------------------*/ From phk at varnish-cache.org Thu Sep 5 08:51:07 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Thu, 05 Sep 2013 10:51:07 +0200 Subject: [master] a583d0c Move the lru timestamp to objcore. Not sure how we managed to forget that in obj. Message-ID: commit a583d0c69387d78da394635c63457bf8029589c6 Author: Poul-Henning Kamp Date: Thu Sep 5 08:50:26 2013 +0000 Move the lru timestamp to objcore. Not sure how we managed to forget that in obj. diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index c104506..7c9b1e0 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -428,6 +428,7 @@ struct objcore { unsigned timer_idx; VTAILQ_ENTRY(objcore) list; VTAILQ_ENTRY(objcore) lru_list; + double last_lru; VTAILQ_ENTRY(objcore) ban_list; struct ban *ban; }; @@ -595,7 +596,6 @@ struct object { struct exp exp; double last_modified; - double last_lru; struct http *http; @@ -836,7 +836,7 @@ void EXP_Set_keep(struct exp *e, double v); double EXP_Ttl(const struct req *, const struct object*); double EXP_Grace(const struct req *, const struct object*); -void EXP_Insert(struct object *o); +void EXP_Insert(const struct object *o); void EXP_Inject(struct objcore *oc, struct lru *lru, double when); void EXP_Init(void); void EXP_Rearm(const struct object *o); diff --git a/bin/varnishd/cache/cache_expire.c b/bin/varnishd/cache/cache_expire.c index 090a209..d764856 100644 --- a/bin/varnishd/cache/cache_expire.c +++ b/bin/varnishd/cache/cache_expire.c @@ -216,7 +216,7 @@ EXP_Inject(struct objcore *oc, struct lru *lru, double when) */ void -EXP_Insert(struct object *o) +EXP_Insert(const struct object *o) { struct objcore *oc; struct lru *lru; @@ -227,7 +227,7 @@ EXP_Insert(struct object *o) HSH_Ref(oc); assert(o->exp.entered != 0 && !isnan(o->exp.entered)); - o->last_lru = o->exp.entered; + oc->last_lru = o->exp.entered; lru = oc_getlru(oc); CHECK_OBJ_NOTNULL(lru, LRU_MAGIC); diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 9ed176e..4a10c14 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -171,10 +171,9 @@ cnt_deliver(struct worker *wrk, struct req *req) req->t_resp = W_TIM_real(wrk); if (!(req->obj->objcore->flags & OC_F_PRIVATE)) { - if ((req->t_resp - req->obj->last_lru) > - cache_param->lru_timeout && - EXP_Touch(req->obj->objcore)) - req->obj->last_lru = req->t_resp; + if ((req->t_resp - req->obj->objcore->last_lru) > + cache_param->lru_timeout && EXP_Touch(req->obj->objcore)) + req->obj->objcore->last_lru = req->t_resp; if (!cache_param->obj_readonly) req->obj->last_use = req->t_resp; /* XXX: locking ? */ } From phk at varnish-cache.org Thu Sep 5 10:28:30 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Thu, 05 Sep 2013 12:28:30 +0200 Subject: [master] b115ccf Move the ws_o structure from struct obj to busyobj, and shave 48 bytes off stored objects. Message-ID: commit b115ccfd98486aff00da25012a1118626b3177f4 Author: Poul-Henning Kamp Date: Thu Sep 5 10:24:32 2013 +0000 Move the ws_o structure from struct obj to busyobj, and shave 48 bytes off stored objects. We used to need this in struct obj, so we could munge obj.http, but we don't allow that any more. diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 7c9b1e0..5be6aab 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -565,6 +565,9 @@ struct busyobj { struct vsl_log vsl[1]; struct dstat *stats; + + /* Workspace for object only needed during fetch */ + struct ws ws_o[1]; }; /* Object structure --------------------------------------------------*/ @@ -578,8 +581,6 @@ struct object { struct storage *objstore; struct objcore *objcore; - struct ws ws_o[1]; - uint8_t *vary; unsigned hits; uint16_t response; @@ -604,7 +605,6 @@ struct object { struct storage *esidata; double last_use; - }; /*--------------------------------------------------------------------*/ diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index 4c926e9..a79e6cc 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -380,7 +380,7 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) obj->vxid = bo->vsl->wid; obj->response = bo->err_code; - WS_Assert(obj->ws_o); + WS_Assert(bo->ws_o); /* Filter into object */ hp = bo->beresp; @@ -408,7 +408,7 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) AN(obj->objcore->ban); } - AZ(obj->ws_o->overflow); + AZ(bo->ws_o->overflow); if (bo->do_stream) HSH_Unbusy(&wrk->stats, obj->objcore); diff --git a/bin/varnishd/cache/cache_panic.c b/bin/varnishd/cache/cache_panic.c index fdd7bb3..ff70390 100644 --- a/bin/varnishd/cache/cache_panic.c +++ b/bin/varnishd/cache/cache_panic.c @@ -208,7 +208,6 @@ pan_object(const struct object *o) VSB_printf(pan_vsp, " obj = %p {\n", o); VSB_printf(pan_vsp, " vxid = %u,\n", o->vxid); - pan_ws(o->ws_o, 4); pan_http("obj", o->http, 4); VSB_printf(pan_vsp, " len = %jd,\n", (intmax_t)o->len); VSB_printf(pan_vsp, " store = {\n"); @@ -279,6 +278,7 @@ pan_busyobj(const struct busyobj *bo) pan_http("bereq", bo->bereq, 4); if (bo->beresp->ws != NULL) pan_http("beresp", bo->beresp, 4); + pan_ws(bo->ws_o, 4); VSB_printf(pan_vsp, " }\n"); } diff --git a/bin/varnishd/storage/stevedore.c b/bin/varnishd/storage/stevedore.c index 5b36c08..2d64d2d 100644 --- a/bin/varnishd/storage/stevedore.c +++ b/bin/varnishd/storage/stevedore.c @@ -277,11 +277,11 @@ STV_MkObject(struct stevedore *stv, struct busyobj *bo, assert(l >= soc->wsl); o->http = HTTP_create(o + 1, soc->nhttp); - WS_Init(o->ws_o, "obj", (char *)(o + 1) + soc->lhttp, soc->wsl); - WS_Assert(o->ws_o); - assert(o->ws_o->e <= (char*)ptr + ltot); + WS_Init(bo->ws_o, "obj", (char *)(o + 1) + soc->lhttp, soc->wsl); + WS_Assert(bo->ws_o); + assert(bo->ws_o->e <= (char*)ptr + ltot); - HTTP_Setup(o->http, o->ws_o, bo->vsl, HTTP_Obj); + HTTP_Setup(o->http, bo->ws_o, bo->vsl, HTTP_Obj); o->http->magic = HTTP_MAGIC; o->exp = bo->exp; VTAILQ_INIT(&o->store); From phk at varnish-cache.org Fri Sep 6 07:00:38 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 09:00:38 +0200 Subject: [master] 4cff3b9 Rename cache_response.c to cache_http1_deliver.c and make it responsible for all deliveries, streaming or non-streaming Message-ID: commit 4cff3b9978e367c4a7425db32376b74c75164e0f Author: Poul-Henning Kamp Date: Thu Sep 5 12:45:15 2013 +0000 Rename cache_response.c to cache_http1_deliver.c and make it responsible for all deliveries, streaming or non-streaming diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am index 4759414..da3480f 100644 --- a/bin/varnishd/Makefile.am +++ b/bin/varnishd/Makefile.am @@ -39,7 +39,7 @@ varnishd_SOURCES = \ cache/cache_pipe.c \ cache/cache_pool.c \ cache/cache_req_fsm.c \ - cache/cache_response.c \ + cache/cache_http1_deliver.c \ cache/cache_rfc2616.c \ cache/cache_session.c \ cache/cache_shmlog.c \ diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 5be6aab..f178691 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -815,6 +815,9 @@ int HTTP1_DiscardReqBody(struct req *req); int HTTP1_CacheReqBody(struct req *req, ssize_t maxsize); int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv); +/* cache_http1_deliver.c */ +void V1D_Deliver(struct req *); + /* cache_req_fsm.c [CNT] */ enum req_fsm_nxt CNT_Request(struct worker *, struct req *); @@ -1052,10 +1055,6 @@ void VSL_Flush(struct vsl_log *, int overflow); #endif -/* cache_response.c */ -void RES_BuildHttp(struct req *); -void RES_WriteObj(struct req *); - /* cache_vary.c */ int VRY_Create(struct busyobj *bo, struct vsb **psb); int VRY_Match(struct req *, const uint8_t *vary); diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c new file mode 100644 index 0000000..4d784d2 --- /dev/null +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -0,0 +1,335 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2011 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include "cache.h" + +#include "vct.h" + +/*--------------------------------------------------------------------*/ + +static void +res_dorange(const struct req *req, const char *r, ssize_t *plow, ssize_t *phigh) +{ + ssize_t low, high, has_low; + + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + assert(req->obj->response == 200); + if (strncmp(r, "bytes=", 6)) + return; + r += 6; + + /* The low end of range */ + has_low = low = 0; + if (!vct_isdigit(*r) && *r != '-') + return; + while (vct_isdigit(*r)) { + has_low = 1; + low *= 10; + low += *r - '0'; + r++; + } + + if (low >= req->obj->len) + return; + + if (*r != '-') + return; + r++; + + /* The high end of range */ + if (vct_isdigit(*r)) { + high = 0; + while (vct_isdigit(*r)) { + high *= 10; + high += *r - '0'; + r++; + } + if (!has_low) { + low = req->obj->len - high; + high = req->obj->len - 1; + } + } else + high = req->obj->len - 1; + if (*r != '\0') + return; + + if (high >= req->obj->len) + high = req->obj->len - 1; + + if (low > high) + return; + + http_PrintfHeader(req->resp, "Content-Range: bytes %jd-%jd/%jd", + (intmax_t)low, (intmax_t)high, (intmax_t)req->obj->len); + http_Unset(req->resp, H_Content_Length); + assert(req->res_mode & RES_LEN); + http_PrintfHeader(req->resp, "Content-Length: %jd", + (intmax_t)(1 + high - low)); + http_SetResp(req->resp, "HTTP/1.1", 206, "Partial Content"); + + *plow = low; + *phigh = high; +} + +/*--------------------------------------------------------------------*/ + +static void +RES_BuildHttp(struct req *req) +{ + + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); + + req->res_mode = 0; + + if (!req->disable_esi && req->obj->esidata != NULL) { + /* In ESI mode, we can't know the aggregate length */ + req->res_mode &= ~RES_LEN; + req->res_mode |= RES_ESI; + } else if (req->obj->objcore->busyobj == NULL) { + /* XXX: Not happy with this convoluted test */ + req->res_mode |= RES_LEN; + if (!(req->obj->objcore->flags & OC_F_PASS) || + req->obj->len != 0) { + http_Unset(req->resp, H_Content_Length); + http_PrintfHeader(req->resp, + "Content-Length: %zd", req->obj->len); + } + if (cache_param->http_range_support) + http_SetHeader(req->resp, "Accept-Ranges: bytes"); + } + + if (req->esi_level > 0) { + /* Included ESI object, always CHUNKED or EOF */ + req->res_mode &= ~RES_LEN; + req->res_mode |= RES_ESI_CHILD; + } + + if (cache_param->http_gzip_support && req->obj->gziped && + !RFC2616_Req_Gzip(req->http)) { + /* + * We don't know what it uncompresses to + * XXX: we could cache that + */ + req->res_mode &= ~RES_LEN; + req->res_mode |= RES_GUNZIP; + } + + if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) { + /* We havn't chosen yet, do so */ + if (!req->wantbody) { + /* Nothing */ + } else if (req->http->protover >= 11) { + req->res_mode |= RES_CHUNKED; + } else { + req->res_mode |= RES_EOF; + req->doclose = SC_TX_EOF; + } + } + VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode); + + if (!(req->res_mode & RES_LEN)) + http_Unset(req->resp, H_Content_Length); + + if (req->res_mode & RES_GUNZIP) + http_Unset(req->resp, H_Content_Encoding); + + if (req->obj->objcore != NULL + && !(req->obj->objcore->flags & OC_F_PASS) + && req->obj->response == 200 + && req->http->conds && RFC2616_Do_Cond(req)) { + req->wantbody = 0; + http_SetResp(req->resp, "HTTP/1.1", 304, "Not Modified"); + http_Unset(req->resp, H_Content_Length); + } else if (req->res_mode & RES_CHUNKED) + http_SetHeader(req->resp, "Transfer-Encoding: chunked"); + + http_PrintfHeader(req->resp, "Connection: %s", + req->doclose ? "close" : "keep-alive"); +} + +/*-------------------------------------------------------------------- + * We have a gzip'ed object and need to ungzip it for a client which + * does not understand gzip. + * XXX: handle invalid gzip data better (how ?) + */ + +static void +res_WriteGunzipObj(struct req *req) +{ + unsigned u = 0; + struct vgz *vg; + struct objiter *oi; + void *ptr; + ssize_t len; + int i; + + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + + vg = VGZ_NewUngzip(req->vsl, "U D -"); + AZ(VGZ_WrwInit(vg)); + + oi = ObjIterBegin(req->obj); + XXXAN(oi); + + while (ObjIter(oi, &ptr, &len)) { + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + u += len; + + i = VGZ_WrwGunzip(req, vg, ptr, len); + /* XXX: error check */ + (void)i; + } + VGZ_WrwFlush(req, vg); + (void)VGZ_Destroy(&vg); + assert(u == req->obj->len); + ObjIterEnd(&oi); +} + +/*--------------------------------------------------------------------*/ + +static void +res_WriteDirObj(struct req *req, ssize_t low, ssize_t high) +{ + ssize_t u = 0; + ssize_t idx, skip, len; + struct objiter *oi; + void *ptr; + + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + + oi = ObjIterBegin(req->obj); + XXXAN(oi); + + idx = 0; + while (ObjIter(oi, &ptr, &len)) { + u += len; + skip = 0; + if (idx + len <= low) { + /* This segment is too early */ + idx += len; + continue; + } + if (idx < low) { + /* Chop front of segment off */ + skip += (low - idx); + len -= (low - idx); + idx += (low - idx); + } + if (idx + len > high) + /* Chop tail of segment off */ + len = 1 + high - idx; + + idx += len; + + req->acct_req.bodybytes += len; + (void)WRW_Write(req->wrk, (char*)ptr + skip, len); + } + assert(u == req->obj->len); + ObjIterEnd(&oi); +} + +/*-------------------------------------------------------------------- + * Deliver an object. + * Attempt optimizations like 304 and 206 here. + */ + +static void +RES_WriteObj(struct req *req) +{ + char *r; + ssize_t low, high; + + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + + /* + * If nothing special planned, we can attempt Range support + */ + low = 0; + high = req->obj->len - 1; + if ( + req->wantbody && + (req->res_mode & RES_LEN) && + !(req->res_mode & (RES_ESI|RES_ESI_CHILD|RES_GUNZIP)) && + cache_param->http_range_support && + req->obj->response == 200 && + http_GetHdr(req->http, H_Range, &r)) + res_dorange(req, r, &low, &high); + + WRW_Reserve(req->wrk, &req->sp->fd, req->vsl, req->t_resp); + + /* + * Send HTTP protocol header, unless interior ESI object + */ + if (!(req->res_mode & RES_ESI_CHILD)) + req->acct_req.hdrbytes += + HTTP1_Write(req->wrk, req->resp, 1); + + if (!req->wantbody) + req->res_mode &= ~RES_CHUNKED; + + if (req->res_mode & RES_CHUNKED) + WRW_Chunked(req->wrk); + + if (!req->wantbody) { + /* This was a HEAD or conditional request */ + } else if (req->obj->len == 0) { + /* Nothing to do here */ + } else if (req->res_mode & RES_ESI) { + ESI_Deliver(req); + } else if (req->res_mode & RES_ESI_CHILD && req->gzip_resp) { + ESI_DeliverChild(req); + } else if (req->res_mode & RES_ESI_CHILD && + !req->gzip_resp && req->obj->gziped) { + res_WriteGunzipObj(req); + } else if (req->res_mode & RES_GUNZIP) { + res_WriteGunzipObj(req); + } else { + res_WriteDirObj(req, low, high); + } + + if (req->res_mode & RES_CHUNKED && + !(req->res_mode & RES_ESI_CHILD)) + WRW_EndChunk(req->wrk); + + if (WRW_FlushRelease(req->wrk) && req->sp->fd >= 0) + SES_Close(req->sp, SC_REM_CLOSE); +} + +void +V1D_Deliver(struct req *req) +{ + while (req->obj->objcore->busyobj) + (void)usleep(10000); + + RES_BuildHttp(req); + RES_WriteObj(req); +} diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 4a10c14..a50b65c 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -76,72 +76,6 @@ DOT acceptor -> recv [style=bold,color=green] #endif /*-------------------------------------------------------------------- - * We have a refcounted object on the session, and possibly the busyobj - * which is fetching it, prepare a response. - * -DOT stream [ -DOT shape=record -DOT label="{cnt_stream:}" -DOT ] -DOT stream:deliver:s -> DONE [style=bold,color=red] -DOT stream:deliver:s -> DONE [style=bold,color=blue] - * - */ - -static enum req_fsm_nxt -cnt_stream(struct worker *wrk, struct req *req) -{ - struct busyobj *bo; - - CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - bo = req->obj->objcore->busyobj; - CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); - AN(bo->do_stream); - - CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); - CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); - - AZ(bo->do_esi); - - if (wrk->handling == VCL_RET_RESTART) { - assert(req->obj == bo->fetch_obj); - req->obj = NULL; - VBO_DerefBusyObj(wrk, &bo); - AZ(req->obj); - http_Teardown(req->resp); - req->req_step = R_STP_RESTART; - return (REQ_FSM_MORE); - } - assert(wrk->handling == VCL_RET_DELIVER); - - VBO_waitstate(bo, BOS_FINISHED); - assert(bo->state >= BOS_FINISHED); - - if (bo->state == BOS_FAILED) { - (void)HSH_DerefObj(&wrk->stats, &req->obj); - VBO_DerefBusyObj(wrk, &bo); - req->err_code = 503; - req->req_step = R_STP_ERROR; - return (REQ_FSM_MORE); - } - VBO_DerefBusyObj(wrk, &bo); - - AZ(bo); - - RES_WriteObj(req); - - /* No point in saving the body if it is hit-for-pass */ - if (req->obj->objcore->flags & OC_F_PASS) - STV_Freestore(req->obj); - - assert(WRW_IsReleased(wrk)); - (void)HSH_DerefObj(&wrk->stats, &req->obj); - http_Teardown(req->resp); - return (REQ_FSM_DONE); -} - -/*-------------------------------------------------------------------- * Deliver an already stored object * DOT deliver [ @@ -202,13 +136,6 @@ cnt_deliver(struct worker *wrk, struct req *req) VCL_deliver_method(req->vcl, wrk, req, NULL, req->http->ws); - while (req->obj->objcore->busyobj) { - VSLb(req->vsl, SLT_Debug, "HERE %s %d", __func__, __LINE__); - (void)usleep(10000); - } - - RES_BuildHttp(req); - /* Stop the insanity before it turns "Hotel California" on us */ if (req->restarts >= cache_param->max_restarts) wrk->handling = VCL_RET_DELIVER; @@ -220,9 +147,10 @@ cnt_deliver(struct worker *wrk, struct req *req) req->req_step = R_STP_RESTART; return (REQ_FSM_MORE); } + assert(wrk->handling == VCL_RET_DELIVER); - RES_WriteObj(req); + V1D_Deliver(req); /* No point in saving the body if it is hit-for-pass */ if (req->obj->objcore->flags & OC_F_PASS) diff --git a/bin/varnishd/cache/cache_response.c b/bin/varnishd/cache/cache_response.c deleted file mode 100644 index c56932e..0000000 --- a/bin/varnishd/cache/cache_response.c +++ /dev/null @@ -1,325 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include "cache.h" - -#include "vct.h" - -/*--------------------------------------------------------------------*/ - -static void -res_dorange(const struct req *req, const char *r, ssize_t *plow, ssize_t *phigh) -{ - ssize_t low, high, has_low; - - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - assert(req->obj->response == 200); - if (strncmp(r, "bytes=", 6)) - return; - r += 6; - - /* The low end of range */ - has_low = low = 0; - if (!vct_isdigit(*r) && *r != '-') - return; - while (vct_isdigit(*r)) { - has_low = 1; - low *= 10; - low += *r - '0'; - r++; - } - - if (low >= req->obj->len) - return; - - if (*r != '-') - return; - r++; - - /* The high end of range */ - if (vct_isdigit(*r)) { - high = 0; - while (vct_isdigit(*r)) { - high *= 10; - high += *r - '0'; - r++; - } - if (!has_low) { - low = req->obj->len - high; - high = req->obj->len - 1; - } - } else - high = req->obj->len - 1; - if (*r != '\0') - return; - - if (high >= req->obj->len) - high = req->obj->len - 1; - - if (low > high) - return; - - http_PrintfHeader(req->resp, "Content-Range: bytes %jd-%jd/%jd", - (intmax_t)low, (intmax_t)high, (intmax_t)req->obj->len); - http_Unset(req->resp, H_Content_Length); - assert(req->res_mode & RES_LEN); - http_PrintfHeader(req->resp, "Content-Length: %jd", - (intmax_t)(1 + high - low)); - http_SetResp(req->resp, "HTTP/1.1", 206, "Partial Content"); - - *plow = low; - *phigh = high; -} - -/*--------------------------------------------------------------------*/ - -void -RES_BuildHttp(struct req *req) -{ - - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); - - req->res_mode = 0; - - if (!req->disable_esi && req->obj->esidata != NULL) { - /* In ESI mode, we can't know the aggregate length */ - req->res_mode &= ~RES_LEN; - req->res_mode |= RES_ESI; - } else if (req->obj->objcore->busyobj == NULL) { - /* XXX: Not happy with this convoluted test */ - req->res_mode |= RES_LEN; - if (!(req->obj->objcore->flags & OC_F_PASS) || - req->obj->len != 0) { - http_Unset(req->resp, H_Content_Length); - http_PrintfHeader(req->resp, - "Content-Length: %zd", req->obj->len); - } - if (cache_param->http_range_support) - http_SetHeader(req->resp, "Accept-Ranges: bytes"); - } - - if (req->esi_level > 0) { - /* Included ESI object, always CHUNKED or EOF */ - req->res_mode &= ~RES_LEN; - req->res_mode |= RES_ESI_CHILD; - } - - if (cache_param->http_gzip_support && req->obj->gziped && - !RFC2616_Req_Gzip(req->http)) { - /* - * We don't know what it uncompresses to - * XXX: we could cache that - */ - req->res_mode &= ~RES_LEN; - req->res_mode |= RES_GUNZIP; - } - - if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) { - /* We havn't chosen yet, do so */ - if (!req->wantbody) { - /* Nothing */ - } else if (req->http->protover >= 11) { - req->res_mode |= RES_CHUNKED; - } else { - req->res_mode |= RES_EOF; - req->doclose = SC_TX_EOF; - } - } - VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode); - - if (!(req->res_mode & RES_LEN)) - http_Unset(req->resp, H_Content_Length); - - if (req->res_mode & RES_GUNZIP) - http_Unset(req->resp, H_Content_Encoding); - - if (req->obj->objcore != NULL - && !(req->obj->objcore->flags & OC_F_PASS) - && req->obj->response == 200 - && req->http->conds && RFC2616_Do_Cond(req)) { - req->wantbody = 0; - http_SetResp(req->resp, "HTTP/1.1", 304, "Not Modified"); - http_Unset(req->resp, H_Content_Length); - } else if (req->res_mode & RES_CHUNKED) - http_SetHeader(req->resp, "Transfer-Encoding: chunked"); - - http_PrintfHeader(req->resp, "Connection: %s", - req->doclose ? "close" : "keep-alive"); -} - -/*-------------------------------------------------------------------- - * We have a gzip'ed object and need to ungzip it for a client which - * does not understand gzip. - * XXX: handle invalid gzip data better (how ?) - */ - -static void -res_WriteGunzipObj(struct req *req) -{ - unsigned u = 0; - struct vgz *vg; - struct objiter *oi; - void *ptr; - ssize_t len; - int i; - - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - - vg = VGZ_NewUngzip(req->vsl, "U D -"); - AZ(VGZ_WrwInit(vg)); - - oi = ObjIterBegin(req->obj); - XXXAN(oi); - - while (ObjIter(oi, &ptr, &len)) { - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - u += len; - - i = VGZ_WrwGunzip(req, vg, ptr, len); - /* XXX: error check */ - (void)i; - } - VGZ_WrwFlush(req, vg); - (void)VGZ_Destroy(&vg); - assert(u == req->obj->len); - ObjIterEnd(&oi); -} - -/*--------------------------------------------------------------------*/ - -static void -res_WriteDirObj(struct req *req, ssize_t low, ssize_t high) -{ - ssize_t u = 0; - ssize_t idx, skip, len; - struct objiter *oi; - void *ptr; - - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - - oi = ObjIterBegin(req->obj); - XXXAN(oi); - - idx = 0; - while (ObjIter(oi, &ptr, &len)) { - u += len; - skip = 0; - if (idx + len <= low) { - /* This segment is too early */ - idx += len; - continue; - } - if (idx < low) { - /* Chop front of segment off */ - skip += (low - idx); - len -= (low - idx); - idx += (low - idx); - } - if (idx + len > high) - /* Chop tail of segment off */ - len = 1 + high - idx; - - idx += len; - - req->acct_req.bodybytes += len; - (void)WRW_Write(req->wrk, (char*)ptr + skip, len); - } - assert(u == req->obj->len); - ObjIterEnd(&oi); -} - -/*-------------------------------------------------------------------- - * Deliver an object. - * Attempt optimizations like 304 and 206 here. - */ - -void -RES_WriteObj(struct req *req) -{ - char *r; - ssize_t low, high; - - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - - /* - * If nothing special planned, we can attempt Range support - */ - low = 0; - high = req->obj->len - 1; - if ( - req->wantbody && - (req->res_mode & RES_LEN) && - !(req->res_mode & (RES_ESI|RES_ESI_CHILD|RES_GUNZIP)) && - cache_param->http_range_support && - req->obj->response == 200 && - http_GetHdr(req->http, H_Range, &r)) - res_dorange(req, r, &low, &high); - - WRW_Reserve(req->wrk, &req->sp->fd, req->vsl, req->t_resp); - - /* - * Send HTTP protocol header, unless interior ESI object - */ - if (!(req->res_mode & RES_ESI_CHILD)) - req->acct_req.hdrbytes += - HTTP1_Write(req->wrk, req->resp, 1); - - if (!req->wantbody) - req->res_mode &= ~RES_CHUNKED; - - if (req->res_mode & RES_CHUNKED) - WRW_Chunked(req->wrk); - - if (!req->wantbody) { - /* This was a HEAD or conditional request */ - } else if (req->obj->len == 0) { - /* Nothing to do here */ - } else if (req->res_mode & RES_ESI) { - ESI_Deliver(req); - } else if (req->res_mode & RES_ESI_CHILD && req->gzip_resp) { - ESI_DeliverChild(req); - } else if (req->res_mode & RES_ESI_CHILD && - !req->gzip_resp && req->obj->gziped) { - res_WriteGunzipObj(req); - } else if (req->res_mode & RES_GUNZIP) { - res_WriteGunzipObj(req); - } else { - res_WriteDirObj(req, low, high); - } - - if (req->res_mode & RES_CHUNKED && - !(req->res_mode & RES_ESI_CHILD)) - WRW_EndChunk(req->wrk); - - if (WRW_FlushRelease(req->wrk) && req->sp->fd >= 0) - SES_Close(req->sp, SC_REM_CLOSE); -} diff --git a/include/tbl/steps.h b/include/tbl/steps.h index 30d331c..34a2315 100644 --- a/include/tbl/steps.h +++ b/include/tbl/steps.h @@ -44,7 +44,6 @@ REQ_STEP(lookup, LOOKUP, (wrk, req)) REQ_STEP(purge, PURGE, (wrk, req)) REQ_STEP(miss, MISS, (wrk, req)) REQ_STEP(fetch, FETCH, (wrk, req)) -REQ_STEP(stream, STREAM, (wrk, req)) REQ_STEP(deliver, DELIVER, (wrk, req)) REQ_STEP(error, ERROR, (wrk, req)) #endif From phk at varnish-cache.org Fri Sep 6 07:00:39 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 09:00:39 +0200 Subject: [master] dd67c0d New VTLA: V1D - HTTP1 delivery Message-ID: commit dd67c0d61f70125e8514e03974cbea3a489f9ad6 Author: Poul-Henning Kamp Date: Thu Sep 5 12:48:55 2013 +0000 New VTLA: V1D - HTTP1 delivery diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index 4d784d2..d758ce5 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp @@ -36,7 +36,7 @@ /*--------------------------------------------------------------------*/ static void -res_dorange(const struct req *req, const char *r, ssize_t *plow, ssize_t *phigh) +v1d_dorange(const struct req *req, const char *r, ssize_t *plow, ssize_t *phigh) { ssize_t low, high, has_low; @@ -102,7 +102,7 @@ res_dorange(const struct req *req, const char *r, ssize_t *plow, ssize_t *phigh) /*--------------------------------------------------------------------*/ static void -RES_BuildHttp(struct req *req) +v1d_BuildHttp(struct req *req) { CHECK_OBJ_NOTNULL(req, REQ_MAGIC); @@ -183,7 +183,7 @@ RES_BuildHttp(struct req *req) */ static void -res_WriteGunzipObj(struct req *req) +v1d_WriteGunzipObj(struct req *req) { unsigned u = 0; struct vgz *vg; @@ -217,7 +217,7 @@ res_WriteGunzipObj(struct req *req) /*--------------------------------------------------------------------*/ static void -res_WriteDirObj(struct req *req, ssize_t low, ssize_t high) +v1d_WriteDirObj(struct req *req, ssize_t low, ssize_t high) { ssize_t u = 0; ssize_t idx, skip, len; @@ -263,7 +263,7 @@ res_WriteDirObj(struct req *req, ssize_t low, ssize_t high) */ static void -RES_WriteObj(struct req *req) +v1d_WriteObj(struct req *req) { char *r; ssize_t low, high; From phk at varnish-cache.org Fri Sep 6 07:00:39 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 09:00:39 +0200 Subject: [master] 2cdfba0 Also rename the function calls. Message-ID: commit 2cdfba04e60a903424673879ef762c14bf86a88e Author: Poul-Henning Kamp Date: Thu Sep 5 12:51:39 2013 +0000 Also rename the function calls. diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index d758ce5..beac565 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -282,7 +282,7 @@ v1d_WriteObj(struct req *req) cache_param->http_range_support && req->obj->response == 200 && http_GetHdr(req->http, H_Range, &r)) - res_dorange(req, r, &low, &high); + v1d_dorange(req, r, &low, &high); WRW_Reserve(req->wrk, &req->sp->fd, req->vsl, req->t_resp); @@ -309,11 +309,11 @@ v1d_WriteObj(struct req *req) ESI_DeliverChild(req); } else if (req->res_mode & RES_ESI_CHILD && !req->gzip_resp && req->obj->gziped) { - res_WriteGunzipObj(req); + v1d_WriteGunzipObj(req); } else if (req->res_mode & RES_GUNZIP) { - res_WriteGunzipObj(req); + v1d_WriteGunzipObj(req); } else { - res_WriteDirObj(req, low, high); + v1d_WriteDirObj(req, low, high); } if (req->res_mode & RES_CHUNKED && @@ -330,6 +330,6 @@ V1D_Deliver(struct req *req) while (req->obj->objcore->busyobj) (void)usleep(10000); - RES_BuildHttp(req); - RES_WriteObj(req); + v1d_BuildHttp(req); + v1d_WriteObj(req); } From phk at varnish-cache.org Fri Sep 6 07:00:39 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 09:00:39 +0200 Subject: [master] f2e4b03 Move code around Message-ID: commit f2e4b033fc302d0c8754bcad320481fccc8accf4 Author: Poul-Henning Kamp Date: Thu Sep 5 13:08:07 2013 +0000 Move code around diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index beac565..83c8953 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -99,83 +99,6 @@ v1d_dorange(const struct req *req, const char *r, ssize_t *plow, ssize_t *phigh) *phigh = high; } -/*--------------------------------------------------------------------*/ - -static void -v1d_BuildHttp(struct req *req) -{ - - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); - - req->res_mode = 0; - - if (!req->disable_esi && req->obj->esidata != NULL) { - /* In ESI mode, we can't know the aggregate length */ - req->res_mode &= ~RES_LEN; - req->res_mode |= RES_ESI; - } else if (req->obj->objcore->busyobj == NULL) { - /* XXX: Not happy with this convoluted test */ - req->res_mode |= RES_LEN; - if (!(req->obj->objcore->flags & OC_F_PASS) || - req->obj->len != 0) { - http_Unset(req->resp, H_Content_Length); - http_PrintfHeader(req->resp, - "Content-Length: %zd", req->obj->len); - } - if (cache_param->http_range_support) - http_SetHeader(req->resp, "Accept-Ranges: bytes"); - } - - if (req->esi_level > 0) { - /* Included ESI object, always CHUNKED or EOF */ - req->res_mode &= ~RES_LEN; - req->res_mode |= RES_ESI_CHILD; - } - - if (cache_param->http_gzip_support && req->obj->gziped && - !RFC2616_Req_Gzip(req->http)) { - /* - * We don't know what it uncompresses to - * XXX: we could cache that - */ - req->res_mode &= ~RES_LEN; - req->res_mode |= RES_GUNZIP; - } - - if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) { - /* We havn't chosen yet, do so */ - if (!req->wantbody) { - /* Nothing */ - } else if (req->http->protover >= 11) { - req->res_mode |= RES_CHUNKED; - } else { - req->res_mode |= RES_EOF; - req->doclose = SC_TX_EOF; - } - } - VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode); - - if (!(req->res_mode & RES_LEN)) - http_Unset(req->resp, H_Content_Length); - - if (req->res_mode & RES_GUNZIP) - http_Unset(req->resp, H_Content_Encoding); - - if (req->obj->objcore != NULL - && !(req->obj->objcore->flags & OC_F_PASS) - && req->obj->response == 200 - && req->http->conds && RFC2616_Do_Cond(req)) { - req->wantbody = 0; - http_SetResp(req->resp, "HTTP/1.1", 304, "Not Modified"); - http_Unset(req->resp, H_Content_Length); - } else if (req->res_mode & RES_CHUNKED) - http_SetHeader(req->resp, "Transfer-Encoding: chunked"); - - http_PrintfHeader(req->resp, "Connection: %s", - req->doclose ? "close" : "keep-alive"); -} - /*-------------------------------------------------------------------- * We have a gzip'ed object and need to ungzip it for a client which * does not understand gzip. @@ -257,18 +180,84 @@ v1d_WriteDirObj(struct req *req, ssize_t low, ssize_t high) ObjIterEnd(&oi); } -/*-------------------------------------------------------------------- - * Deliver an object. - * Attempt optimizations like 304 and 206 here. - */ - -static void -v1d_WriteObj(struct req *req) +void +V1D_Deliver(struct req *req) { char *r; ssize_t low, high; CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); + + while (req->obj->objcore->busyobj) + (void)usleep(10000); + + req->res_mode = 0; + + if (!req->disable_esi && req->obj->esidata != NULL) { + /* In ESI mode, we can't know the aggregate length */ + req->res_mode &= ~RES_LEN; + req->res_mode |= RES_ESI; + } else if (req->obj->objcore->busyobj == NULL) { + /* XXX: Not happy with this convoluted test */ + req->res_mode |= RES_LEN; + if (!(req->obj->objcore->flags & OC_F_PASS) || + req->obj->len != 0) { + http_Unset(req->resp, H_Content_Length); + http_PrintfHeader(req->resp, + "Content-Length: %zd", req->obj->len); + } + if (cache_param->http_range_support) + http_SetHeader(req->resp, "Accept-Ranges: bytes"); + } + + if (req->esi_level > 0) { + /* Included ESI object, always CHUNKED or EOF */ + req->res_mode &= ~RES_LEN; + req->res_mode |= RES_ESI_CHILD; + } + + if (cache_param->http_gzip_support && req->obj->gziped && + !RFC2616_Req_Gzip(req->http)) { + /* + * We don't know what it uncompresses to + * XXX: we could cache that + */ + req->res_mode &= ~RES_LEN; + req->res_mode |= RES_GUNZIP; + } + + if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) { + /* We havn't chosen yet, do so */ + if (!req->wantbody) { + /* Nothing */ + } else if (req->http->protover >= 11) { + req->res_mode |= RES_CHUNKED; + } else { + req->res_mode |= RES_EOF; + req->doclose = SC_TX_EOF; + } + } + VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode); + + if (!(req->res_mode & RES_LEN)) + http_Unset(req->resp, H_Content_Length); + + if (req->res_mode & RES_GUNZIP) + http_Unset(req->resp, H_Content_Encoding); + + if (req->obj->objcore != NULL + && !(req->obj->objcore->flags & OC_F_PASS) + && req->obj->response == 200 + && req->http->conds && RFC2616_Do_Cond(req)) { + req->wantbody = 0; + http_SetResp(req->resp, "HTTP/1.1", 304, "Not Modified"); + http_Unset(req->resp, H_Content_Length); + } else if (req->res_mode & RES_CHUNKED) + http_SetHeader(req->resp, "Transfer-Encoding: chunked"); + + http_PrintfHeader(req->resp, "Connection: %s", + req->doclose ? "close" : "keep-alive"); /* * If nothing special planned, we can attempt Range support @@ -316,20 +305,9 @@ v1d_WriteObj(struct req *req) v1d_WriteDirObj(req, low, high); } - if (req->res_mode & RES_CHUNKED && - !(req->res_mode & RES_ESI_CHILD)) + if (req->res_mode & RES_CHUNKED && !(req->res_mode & RES_ESI_CHILD)) WRW_EndChunk(req->wrk); if (WRW_FlushRelease(req->wrk) && req->sp->fd >= 0) SES_Close(req->sp, SC_REM_CLOSE); } - -void -V1D_Deliver(struct req *req) -{ - while (req->obj->objcore->busyobj) - (void)usleep(10000); - - v1d_BuildHttp(req); - v1d_WriteObj(req); -} From phk at varnish-cache.org Fri Sep 6 07:00:39 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 09:00:39 +0200 Subject: [master] fb5cd02 minor polish Message-ID: commit fb5cd02860033e580315200ddebf2d950fec6ecb Author: Poul-Henning Kamp Date: Thu Sep 5 14:08:49 2013 +0000 minor polish diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index 83c8953..0b47331 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -188,6 +188,7 @@ V1D_Deliver(struct req *req) CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); + CHECK_OBJ_NOTNULL(req->obj->objcore, OBJCORE_MAGIC); while (req->obj->objcore->busyobj) (void)usleep(10000); @@ -221,7 +222,8 @@ V1D_Deliver(struct req *req) !RFC2616_Req_Gzip(req->http)) { /* * We don't know what it uncompresses to - * XXX: we could cache that + * XXX: we could cache that, but would still deliver + * XXX: with multiple writes because of the gunzip buffer */ req->res_mode &= ~RES_LEN; req->res_mode |= RES_GUNZIP; @@ -246,8 +248,7 @@ V1D_Deliver(struct req *req) if (req->res_mode & RES_GUNZIP) http_Unset(req->resp, H_Content_Encoding); - if (req->obj->objcore != NULL - && !(req->obj->objcore->flags & OC_F_PASS) + if (!(req->obj->objcore->flags & OC_F_PASS) && req->obj->response == 200 && req->http->conds && RFC2616_Do_Cond(req)) { req->wantbody = 0; @@ -256,14 +257,15 @@ V1D_Deliver(struct req *req) } else if (req->res_mode & RES_CHUNKED) http_SetHeader(req->resp, "Transfer-Encoding: chunked"); - http_PrintfHeader(req->resp, "Connection: %s", - req->doclose ? "close" : "keep-alive"); + http_SetHeader(req->resp, + req->doclose ? "Connection: close" : "Connection: keep-alive"); /* * If nothing special planned, we can attempt Range support */ low = 0; high = req->obj->len - 1; + if ( req->wantbody && (req->res_mode & RES_LEN) && @@ -279,8 +281,7 @@ V1D_Deliver(struct req *req) * Send HTTP protocol header, unless interior ESI object */ if (!(req->res_mode & RES_ESI_CHILD)) - req->acct_req.hdrbytes += - HTTP1_Write(req->wrk, req->resp, 1); + req->acct_req.hdrbytes += HTTP1_Write(req->wrk, req->resp, 1); if (!req->wantbody) req->res_mode &= ~RES_CHUNKED; From phk at varnish-cache.org Fri Sep 6 07:00:39 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 09:00:39 +0200 Subject: [master] 2f0c9c3 Add yet a VTLA: "VDP" Delivery processors Message-ID: commit 2f0c9c3ce4b17ed0b50c8a79065c6cbe95430e99 Author: Poul-Henning Kamp Date: Thu Sep 5 15:44:45 2013 +0000 Add yet a VTLA: "VDP" Delivery processors These are stackable, and does stuff on the way out. The bottom one points to HTTP/1 ie. WRW for now. On top of that we can push Range: processing. Modularizing this, makes it trivial to enable Range: support for delivery-side gunzip. (Committed above the Elbe) diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index f178691..7115141 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -120,6 +120,7 @@ struct object; struct objhead; struct pool; struct poolparam; +struct req; struct sess; struct sesspool; struct vbc; @@ -275,6 +276,10 @@ extern struct vfp vfp_gzip; extern struct vfp vfp_testgzip; extern struct vfp vfp_esi; +/* Deliver processors ------------------------------------------------*/ + +typedef int vdp_bytes(struct req *, int flush, void *ptr, ssize_t len); + /*--------------------------------------------------------------------*/ struct exp { @@ -690,6 +695,15 @@ struct req { #define RES_ESI_CHILD (1<<5) #define RES_GUNZIP (1<<6) + /* Deliver pipeline */ + vdp_bytes *vdps[5]; + int vdp_nxt; + + /* Range */ + ssize_t range_low; + ssize_t range_high; + ssize_t range_off; + /* Transaction VSL buffer */ struct vsl_log vsl[1]; @@ -818,6 +832,18 @@ int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv); /* cache_http1_deliver.c */ void V1D_Deliver(struct req *); +static inline int +VDP(struct req *req, int flush, void *ptr, ssize_t len) +{ + int i, retval; + + /* Call the present layer, while pointing to the next layer down */ + i = req->vdp_nxt--; + retval = req->vdps[i](req, flush, ptr, len); + req->vdp_nxt++; + return (retval); +} + /* cache_req_fsm.c [CNT] */ enum req_fsm_nxt CNT_Request(struct worker *, struct req *); diff --git a/bin/varnishd/cache/cache_gzip.c b/bin/varnishd/cache/cache_gzip.c index be633d3..a5b2cbd 100644 --- a/bin/varnishd/cache/cache_gzip.c +++ b/bin/varnishd/cache/cache_gzip.c @@ -342,9 +342,7 @@ VGZ_WrwGunzip(struct req *req, struct vgz *vg, const void *ibuf, if (vr < VGZ_OK) return (vr); if (vg->m_len == vg->m_sz || vr == VGZ_STUCK) { - req->acct_req.bodybytes += vg->m_len; - (void)WRW_Write(wrk, vg->m_buf, vg->m_len); - (void)WRW_Flush(wrk); + (void)VDP(req, 1, vg->m_buf, vg->m_len); vg->m_len = 0; VGZ_Obuf(vg, vg->m_buf, vg->m_sz); } @@ -369,9 +367,7 @@ VGZ_WrwFlush(struct req *req, struct vgz *vg) if (vg->m_len == 0) return; - req->acct_req.bodybytes += vg->m_len; - (void)WRW_Write(wrk, vg->m_buf, vg->m_len); - (void)WRW_Flush(wrk); + (void)VDP(req, 1, vg->m_buf, vg->m_len); vg->m_len = 0; VGZ_Obuf(vg, vg->m_buf, vg->m_sz); } diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index 0b47331..6abae76 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -35,8 +35,57 @@ /*--------------------------------------------------------------------*/ +static int __match_proto__(vdp_bytes) +v1d_bytes(struct req *req, int flush, void *ptr, ssize_t len) +{ + ssize_t wl = 0; + + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + + assert(req->vdp_nxt == -1); /* always at the bottom of the pile */ + + if (len > 0) + wl = WRW_Write(req->wrk, ptr, len); + if (wl > 0) + req->acct_req.bodybytes += wl; + if (flush && WRW_Flush(req->wrk)) + return (-1); + if (len != wl) + return (-1); + return (0); +} + +/*--------------------------------------------------------------------*/ + +static int __match_proto__(vdp_bytes) +v1d_range_bytes(struct req *req, int flush, void *ptr, ssize_t len) +{ + int retval = 0; + ssize_t l; + char *p = ptr; + + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + l = req->range_low - req->range_off; + if (l > 0) { + if (l > len) + l = len; + req->range_off += l; + p += l; + len -= l; + } + l = req->range_high - req->range_off; + if (l > len) + l = len; + if (flush || l > 0) + retval = VDP(req, flush, p, l); + req->range_off += len; + return (retval); +} + +/*--------------------------------------------------------------------*/ + static void -v1d_dorange(const struct req *req, const char *r, ssize_t *plow, ssize_t *phigh) +v1d_dorange(struct req *req, const char *r) { ssize_t low, high, has_low; @@ -90,13 +139,15 @@ v1d_dorange(const struct req *req, const char *r, ssize_t *plow, ssize_t *phigh) http_PrintfHeader(req->resp, "Content-Range: bytes %jd-%jd/%jd", (intmax_t)low, (intmax_t)high, (intmax_t)req->obj->len); http_Unset(req->resp, H_Content_Length); - assert(req->res_mode & RES_LEN); - http_PrintfHeader(req->resp, "Content-Length: %jd", - (intmax_t)(1 + high - low)); + if (req->res_mode & RES_LEN) + http_PrintfHeader(req->resp, "Content-Length: %jd", + (intmax_t)(1 + high - low)); http_SetResp(req->resp, "HTTP/1.1", 206, "Partial Content"); - *plow = low; - *phigh = high; + req->range_off = 0; + req->range_low = low; + req->range_high = high + 1; + req->vdps[++req->vdp_nxt] = v1d_range_bytes; } /*-------------------------------------------------------------------- @@ -140,10 +191,9 @@ v1d_WriteGunzipObj(struct req *req) /*--------------------------------------------------------------------*/ static void -v1d_WriteDirObj(struct req *req, ssize_t low, ssize_t high) +v1d_WriteDirObj(struct req *req) { - ssize_t u = 0; - ssize_t idx, skip, len; + ssize_t len; struct objiter *oi; void *ptr; @@ -152,31 +202,10 @@ v1d_WriteDirObj(struct req *req, ssize_t low, ssize_t high) oi = ObjIterBegin(req->obj); XXXAN(oi); - idx = 0; while (ObjIter(oi, &ptr, &len)) { - u += len; - skip = 0; - if (idx + len <= low) { - /* This segment is too early */ - idx += len; - continue; - } - if (idx < low) { - /* Chop front of segment off */ - skip += (low - idx); - len -= (low - idx); - idx += (low - idx); - } - if (idx + len > high) - /* Chop tail of segment off */ - len = 1 + high - idx; - - idx += len; - - req->acct_req.bodybytes += len; - (void)WRW_Write(req->wrk, (char*)ptr + skip, len); + if (VDP(req, 0, ptr, len)) + break; } - assert(u == req->obj->len); ObjIterEnd(&oi); } @@ -184,7 +213,6 @@ void V1D_Deliver(struct req *req) { char *r; - ssize_t low, high; CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); @@ -263,17 +291,19 @@ V1D_Deliver(struct req *req) /* * If nothing special planned, we can attempt Range support */ - low = 0; - high = req->obj->len - 1; + req->range_low = 0; + req->range_high = req->obj->len - 1; + + req->vdps[0] = v1d_bytes; + req->vdp_nxt = 0; if ( req->wantbody && - (req->res_mode & RES_LEN) && - !(req->res_mode & (RES_ESI|RES_ESI_CHILD|RES_GUNZIP)) && + !(req->res_mode & (RES_ESI|RES_ESI_CHILD)) && cache_param->http_range_support && req->obj->response == 200 && http_GetHdr(req->http, H_Range, &r)) - v1d_dorange(req, r, &low, &high); + v1d_dorange(req, r); WRW_Reserve(req->wrk, &req->sp->fd, req->vsl, req->t_resp); @@ -303,7 +333,7 @@ V1D_Deliver(struct req *req) } else if (req->res_mode & RES_GUNZIP) { v1d_WriteGunzipObj(req); } else { - v1d_WriteDirObj(req, low, high); + v1d_WriteDirObj(req); } if (req->res_mode & RES_CHUNKED && !(req->res_mode & RES_ESI_CHILD)) diff --git a/bin/varnishtest/tests/g00005.vtc b/bin/varnishtest/tests/g00005.vtc new file mode 100644 index 0000000..9917937 --- /dev/null +++ b/bin/varnishtest/tests/g00005.vtc @@ -0,0 +1,30 @@ +varnishtest "test gunzip for client + Range" + +server s1 { + rxreq + expect req.http.accept-encoding == "gzip" + txresp -gzipbody FOOBARBARF +} -start + +varnish v1 -cliok "param.set http_gzip_support true" -vcl+backend { +} -start + +client c1 { + txreq + rxresp + expect resp.bodylen == "10" + expect resp.http.content-encoding == + + txreq -hdr "Accept-encoding: gzip;q=0.1" + rxresp + expect resp.http.content-encoding == "gzip" + gunzip + expect resp.bodylen == "10" + + txreq -hdr "Range: bytes=3-5" + rxresp + expect resp.http.content-encoding == "" + expect resp.bodylen == "3" + expect resp.body == "BAR" + +} -run From phk at varnish-cache.org Fri Sep 6 07:00:39 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 09:00:39 +0200 Subject: [master] e44815a Turn delivery-side gunzip into a VDP Message-ID: commit e44815ad1a8bab42d014ebd2ca2cf5708792ec8c Author: Poul-Henning Kamp Date: Thu Sep 5 16:25:08 2013 +0000 Turn delivery-side gunzip into a VDP diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 7115141..d6ae10d 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -696,7 +696,8 @@ struct req { #define RES_GUNZIP (1<<6) /* Deliver pipeline */ - vdp_bytes *vdps[5]; +#define N_VDPS 5 + vdp_bytes *vdps[N_VDPS]; int vdp_nxt; /* Range */ @@ -704,6 +705,9 @@ struct req { ssize_t range_high; ssize_t range_off; + /* Gunzip */ + struct vgz *vgz; + /* Transaction VSL buffer */ struct vsl_log vsl[1]; @@ -833,17 +837,44 @@ int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv); void V1D_Deliver(struct req *); static inline int -VDP(struct req *req, int flush, void *ptr, ssize_t len) +VDP_bytes(struct req *req, int flush, void *ptr, ssize_t len) { int i, retval; + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + /* Call the present layer, while pointing to the next layer down */ i = req->vdp_nxt--; + assert(i >= 0 && i < N_VDPS); retval = req->vdps[i](req, flush, ptr, len); req->vdp_nxt++; return (retval); } +static inline void +VDP_push(struct req *req, vdp_bytes *func) +{ + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + AN(func); + + /* Push another layer */ + assert(req->vdp_nxt >= 0); + assert(req->vdp_nxt + 1 < N_VDPS); + req->vdps[++req->vdp_nxt] = func; +} + +static inline void +VDP_pop(struct req *req, vdp_bytes *func) +{ + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + + /* Pop top layer */ + assert(req->vdp_nxt >= 1); + assert(req->vdp_nxt < N_VDPS); + assert(req->vdps[req->vdp_nxt] == func); + req->vdp_nxt--; +} + /* cache_req_fsm.c [CNT] */ enum req_fsm_nxt CNT_Request(struct worker *, struct req *); @@ -911,6 +942,7 @@ enum vgzret_e VGZ_Gzip(struct vgz *, const void **, size_t *len, enum vgz_flag); enum vgzret_e VGZ_Gunzip(struct vgz *, const void **, size_t *len); enum vgzret_e VGZ_Destroy(struct vgz **); void VGZ_UpdateObj(const struct vgz*, struct object *); +vdp_bytes VDP_gunzip; int VGZ_WrwInit(struct vgz *vg); enum vgzret_e VGZ_WrwGunzip(struct req *, struct vgz *, const void *ibuf, diff --git a/bin/varnishd/cache/cache_gzip.c b/bin/varnishd/cache/cache_gzip.c index a5b2cbd..6bbf07a 100644 --- a/bin/varnishd/cache/cache_gzip.c +++ b/bin/varnishd/cache/cache_gzip.c @@ -311,6 +311,53 @@ VGZ_WrwInit(struct vgz *vg) } /*-------------------------------------------------------------------- + * VDP for gunzip'ing + */ + +int __match_proto__(vdp_bytes) +VDP_gunzip(struct req *req, int flush, void *ptr, ssize_t len) +{ + enum vgzret_e vr; + size_t dl; + const void *dp; + struct worker *wrk; + struct vgz *vg; + + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + wrk = req->wrk; + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + vg = req->vgz; + CHECK_OBJ_NOTNULL(vg, VGZ_MAGIC); + AN(vg->m_buf); + + if (len == 0) { + AN(flush); + return (VDP_bytes(req, 1, vg->m_buf, vg->m_len)); + } + + VGZ_Ibuf(vg, ptr, len); + do { + if (vg->m_len == vg->m_sz) + vr = VGZ_STUCK; + else { + vr = VGZ_Gunzip(vg, &dp, &dl); + vg->m_len += dl; + } + if (vr < VGZ_OK) + return (-1); + if (vg->m_len == vg->m_sz || vr == VGZ_STUCK) { + if (VDP_bytes(req, 1, vg->m_buf, vg->m_len)) + return (-1); + vg->m_len = 0; + VGZ_Obuf(vg, vg->m_buf, vg->m_sz); + } + } while (!VGZ_IbufEmpty(vg)); + assert(vr == VGZ_STUCK || vr == VGZ_OK || vr == VGZ_END); + return (0); +} + + +/*-------------------------------------------------------------------- * Gunzip ibuf into outb, if it runs full, emit it with WRW. * Leave flushing to caller, more data may be coming. */ @@ -342,7 +389,7 @@ VGZ_WrwGunzip(struct req *req, struct vgz *vg, const void *ibuf, if (vr < VGZ_OK) return (vr); if (vg->m_len == vg->m_sz || vr == VGZ_STUCK) { - (void)VDP(req, 1, vg->m_buf, vg->m_len); + (void)VDP_bytes(req, 1, vg->m_buf, vg->m_len); vg->m_len = 0; VGZ_Obuf(vg, vg->m_buf, vg->m_sz); } @@ -367,7 +414,7 @@ VGZ_WrwFlush(struct req *req, struct vgz *vg) if (vg->m_len == 0) return; - (void)VDP(req, 1, vg->m_buf, vg->m_len); + (void)VDP_bytes(req, 1, vg->m_buf, vg->m_len); vg->m_len = 0; VGZ_Obuf(vg, vg->m_buf, vg->m_sz); } diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index 6abae76..1d111e9 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -77,7 +77,7 @@ v1d_range_bytes(struct req *req, int flush, void *ptr, ssize_t len) if (l > len) l = len; if (flush || l > 0) - retval = VDP(req, flush, p, l); + retval = VDP_bytes(req, flush, p, l); req->range_off += len; return (retval); } @@ -147,45 +147,7 @@ v1d_dorange(struct req *req, const char *r) req->range_off = 0; req->range_low = low; req->range_high = high + 1; - req->vdps[++req->vdp_nxt] = v1d_range_bytes; -} - -/*-------------------------------------------------------------------- - * We have a gzip'ed object and need to ungzip it for a client which - * does not understand gzip. - * XXX: handle invalid gzip data better (how ?) - */ - -static void -v1d_WriteGunzipObj(struct req *req) -{ - unsigned u = 0; - struct vgz *vg; - struct objiter *oi; - void *ptr; - ssize_t len; - int i; - - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - - vg = VGZ_NewUngzip(req->vsl, "U D -"); - AZ(VGZ_WrwInit(vg)); - - oi = ObjIterBegin(req->obj); - XXXAN(oi); - - while (ObjIter(oi, &ptr, &len)) { - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - u += len; - - i = VGZ_WrwGunzip(req, vg, ptr, len); - /* XXX: error check */ - (void)i; - } - VGZ_WrwFlush(req, vg); - (void)VGZ_Destroy(&vg); - assert(u == req->obj->len); - ObjIterEnd(&oi); + VDP_push(req, v1d_range_bytes); } /*--------------------------------------------------------------------*/ @@ -203,9 +165,10 @@ v1d_WriteDirObj(struct req *req) XXXAN(oi); while (ObjIter(oi, &ptr, &len)) { - if (VDP(req, 0, ptr, len)) + if (VDP_bytes(req, 0, ptr, len)) break; } + (void)VDP_bytes(req, 1, NULL, 0); ObjIterEnd(&oi); } @@ -329,9 +292,19 @@ V1D_Deliver(struct req *req) ESI_DeliverChild(req); } else if (req->res_mode & RES_ESI_CHILD && !req->gzip_resp && req->obj->gziped) { - v1d_WriteGunzipObj(req); + VDP_push(req, VDP_gunzip); + req->vgz = VGZ_NewUngzip(req->vsl, "U D -"); + AZ(VGZ_WrwInit(req->vgz)); + v1d_WriteDirObj(req); + (void)VGZ_Destroy(&req->vgz); + VDP_pop(req, VDP_gunzip); } else if (req->res_mode & RES_GUNZIP) { - v1d_WriteGunzipObj(req); + VDP_push(req, VDP_gunzip); + req->vgz = VGZ_NewUngzip(req->vsl, "U D -"); + AZ(VGZ_WrwInit(req->vgz)); + v1d_WriteDirObj(req); + (void)VGZ_Destroy(&req->vgz); + VDP_pop(req, VDP_gunzip); } else { v1d_WriteDirObj(req); } From phk at varnish-cache.org Fri Sep 6 07:00:39 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 09:00:39 +0200 Subject: [master] 4f435ce Polish Message-ID: commit 4f435cef4953e8bef81e89049d4a597d074c4c57 Author: Poul-Henning Kamp Date: Thu Sep 5 16:41:44 2013 +0000 Polish diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index d6ae10d..ab827d3 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -278,7 +278,12 @@ extern struct vfp vfp_esi; /* Deliver processors ------------------------------------------------*/ -typedef int vdp_bytes(struct req *, int flush, void *ptr, ssize_t len); +enum vdp_action { + VDP_NULL, + VDP_FLUSH, + VDP_FINISH, +}; +typedef int vdp_bytes(struct req *, enum vdp_action, void *ptr, ssize_t len); /*--------------------------------------------------------------------*/ @@ -837,7 +842,7 @@ int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv); void V1D_Deliver(struct req *); static inline int -VDP_bytes(struct req *req, int flush, void *ptr, ssize_t len) +VDP_bytes(struct req *req, enum vdp_action act, void *ptr, ssize_t len) { int i, retval; @@ -846,7 +851,7 @@ VDP_bytes(struct req *req, int flush, void *ptr, ssize_t len) /* Call the present layer, while pointing to the next layer down */ i = req->vdp_nxt--; assert(i >= 0 && i < N_VDPS); - retval = req->vdps[i](req, flush, ptr, len); + retval = req->vdps[i](req, act, ptr, len); req->vdp_nxt++; return (retval); } diff --git a/bin/varnishd/cache/cache_gzip.c b/bin/varnishd/cache/cache_gzip.c index 6bbf07a..9f42529 100644 --- a/bin/varnishd/cache/cache_gzip.c +++ b/bin/varnishd/cache/cache_gzip.c @@ -315,7 +315,7 @@ VGZ_WrwInit(struct vgz *vg) */ int __match_proto__(vdp_bytes) -VDP_gunzip(struct req *req, int flush, void *ptr, ssize_t len) +VDP_gunzip(struct req *req, enum vdp_action act, void *ptr, ssize_t len) { enum vgzret_e vr; size_t dl; @@ -331,8 +331,8 @@ VDP_gunzip(struct req *req, int flush, void *ptr, ssize_t len) AN(vg->m_buf); if (len == 0) { - AN(flush); - return (VDP_bytes(req, 1, vg->m_buf, vg->m_len)); + AN(act > VDP_NULL); + return (VDP_bytes(req, act, vg->m_buf, vg->m_len)); } VGZ_Ibuf(vg, ptr, len); @@ -346,7 +346,7 @@ VDP_gunzip(struct req *req, int flush, void *ptr, ssize_t len) if (vr < VGZ_OK) return (-1); if (vg->m_len == vg->m_sz || vr == VGZ_STUCK) { - if (VDP_bytes(req, 1, vg->m_buf, vg->m_len)) + if (VDP_bytes(req, VDP_FLUSH, vg->m_buf, vg->m_len)) return (-1); vg->m_len = 0; VGZ_Obuf(vg, vg->m_buf, vg->m_sz); @@ -389,7 +389,7 @@ VGZ_WrwGunzip(struct req *req, struct vgz *vg, const void *ibuf, if (vr < VGZ_OK) return (vr); if (vg->m_len == vg->m_sz || vr == VGZ_STUCK) { - (void)VDP_bytes(req, 1, vg->m_buf, vg->m_len); + (void)VDP_bytes(req, VDP_FLUSH, vg->m_buf, vg->m_len); vg->m_len = 0; VGZ_Obuf(vg, vg->m_buf, vg->m_sz); } @@ -414,7 +414,7 @@ VGZ_WrwFlush(struct req *req, struct vgz *vg) if (vg->m_len == 0) return; - (void)VDP_bytes(req, 1, vg->m_buf, vg->m_len); + (void)VDP_bytes(req, VDP_FLUSH, vg->m_buf, vg->m_len); vg->m_len = 0; VGZ_Obuf(vg, vg->m_buf, vg->m_sz); } diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index 1d111e9..c57b977 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -36,7 +36,7 @@ /*--------------------------------------------------------------------*/ static int __match_proto__(vdp_bytes) -v1d_bytes(struct req *req, int flush, void *ptr, ssize_t len) +v1d_bytes(struct req *req, enum vdp_action act, void *ptr, ssize_t len) { ssize_t wl = 0; @@ -48,7 +48,7 @@ v1d_bytes(struct req *req, int flush, void *ptr, ssize_t len) wl = WRW_Write(req->wrk, ptr, len); if (wl > 0) req->acct_req.bodybytes += wl; - if (flush && WRW_Flush(req->wrk)) + if (act > VDP_NULL && WRW_Flush(req->wrk)) return (-1); if (len != wl) return (-1); @@ -58,7 +58,7 @@ v1d_bytes(struct req *req, int flush, void *ptr, ssize_t len) /*--------------------------------------------------------------------*/ static int __match_proto__(vdp_bytes) -v1d_range_bytes(struct req *req, int flush, void *ptr, ssize_t len) +v1d_range_bytes(struct req *req, enum vdp_action act, void *ptr, ssize_t len) { int retval = 0; ssize_t l; @@ -76,8 +76,8 @@ v1d_range_bytes(struct req *req, int flush, void *ptr, ssize_t len) l = req->range_high - req->range_off; if (l > len) l = len; - if (flush || l > 0) - retval = VDP_bytes(req, flush, p, l); + if (act > VDP_NULL || l > 0) + retval = VDP_bytes(req, act, p, l); req->range_off += len; return (retval); } @@ -165,10 +165,10 @@ v1d_WriteDirObj(struct req *req) XXXAN(oi); while (ObjIter(oi, &ptr, &len)) { - if (VDP_bytes(req, 0, ptr, len)) + if (VDP_bytes(req, VDP_NULL, ptr, len)) break; } - (void)VDP_bytes(req, 1, NULL, 0); + (void)VDP_bytes(req, VDP_FINISH, NULL, 0); ObjIterEnd(&oi); } @@ -290,15 +290,9 @@ V1D_Deliver(struct req *req) ESI_Deliver(req); } else if (req->res_mode & RES_ESI_CHILD && req->gzip_resp) { ESI_DeliverChild(req); - } else if (req->res_mode & RES_ESI_CHILD && - !req->gzip_resp && req->obj->gziped) { - VDP_push(req, VDP_gunzip); - req->vgz = VGZ_NewUngzip(req->vsl, "U D -"); - AZ(VGZ_WrwInit(req->vgz)); - v1d_WriteDirObj(req); - (void)VGZ_Destroy(&req->vgz); - VDP_pop(req, VDP_gunzip); - } else if (req->res_mode & RES_GUNZIP) { + } else if (req->res_mode & RES_GUNZIP || + (req->res_mode & RES_ESI_CHILD && + !req->gzip_resp && req->obj->gziped)) { VDP_push(req, VDP_gunzip); req->vgz = VGZ_NewUngzip(req->vsl, "U D -"); AZ(VGZ_WrwInit(req->vgz)); From phk at varnish-cache.org Fri Sep 6 07:00:39 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 09:00:39 +0200 Subject: [master] 217c0e2 Make the VDP ptr argument const Message-ID: commit 217c0e24feda130fdb1fc7cb64b083affcf7bd12 Author: Poul-Henning Kamp Date: Thu Sep 5 22:14:28 2013 +0000 Make the VDP ptr argument const diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index ab827d3..cc2f963 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -283,7 +283,8 @@ enum vdp_action { VDP_FLUSH, VDP_FINISH, }; -typedef int vdp_bytes(struct req *, enum vdp_action, void *ptr, ssize_t len); +typedef int vdp_bytes(struct req *, enum vdp_action, const void *ptr, + ssize_t len); /*--------------------------------------------------------------------*/ @@ -842,7 +843,7 @@ int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv); void V1D_Deliver(struct req *); static inline int -VDP_bytes(struct req *req, enum vdp_action act, void *ptr, ssize_t len) +VDP_bytes(struct req *req, enum vdp_action act, const void *ptr, ssize_t len) { int i, retval; diff --git a/bin/varnishd/cache/cache_gzip.c b/bin/varnishd/cache/cache_gzip.c index 9f42529..6eab8a4 100644 --- a/bin/varnishd/cache/cache_gzip.c +++ b/bin/varnishd/cache/cache_gzip.c @@ -315,7 +315,7 @@ VGZ_WrwInit(struct vgz *vg) */ int __match_proto__(vdp_bytes) -VDP_gunzip(struct req *req, enum vdp_action act, void *ptr, ssize_t len) +VDP_gunzip(struct req *req, enum vdp_action act, const void *ptr, ssize_t len) { enum vgzret_e vr; size_t dl; diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index c57b977..7206ff4 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -36,7 +36,7 @@ /*--------------------------------------------------------------------*/ static int __match_proto__(vdp_bytes) -v1d_bytes(struct req *req, enum vdp_action act, void *ptr, ssize_t len) +v1d_bytes(struct req *req, enum vdp_action act, const void *ptr, ssize_t len) { ssize_t wl = 0; @@ -58,11 +58,12 @@ v1d_bytes(struct req *req, enum vdp_action act, void *ptr, ssize_t len) /*--------------------------------------------------------------------*/ static int __match_proto__(vdp_bytes) -v1d_range_bytes(struct req *req, enum vdp_action act, void *ptr, ssize_t len) +v1d_range_bytes(struct req *req, enum vdp_action act, const void *ptr, + ssize_t len) { int retval = 0; ssize_t l; - char *p = ptr; + const char *p = ptr; CHECK_OBJ_NOTNULL(req, REQ_MAGIC); l = req->range_low - req->range_off; From phk at varnish-cache.org Fri Sep 6 07:00:39 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 09:00:39 +0200 Subject: [master] 12fc791 Polish Message-ID: commit 12fc791ed341806b87821e6c52cc7722eeebfe9d Author: Poul-Henning Kamp Date: Thu Sep 5 22:35:43 2013 +0000 Polish diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index 7206ff4..d20e90b 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -252,12 +252,6 @@ V1D_Deliver(struct req *req) http_SetHeader(req->resp, req->doclose ? "Connection: close" : "Connection: keep-alive"); - /* - * If nothing special planned, we can attempt Range support - */ - req->range_low = 0; - req->range_high = req->obj->len - 1; - req->vdps[0] = v1d_bytes; req->vdp_nxt = 0; From phk at varnish-cache.org Fri Sep 6 21:50:45 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 23:50:45 +0200 Subject: [master] 4b33a2f Fix buglet Message-ID: commit 4b33a2fcd28d1ba3d4ab254150c661bdd2d08ec2 Author: Poul-Henning Kamp Date: Fri Sep 6 16:44:04 2013 +0000 Fix buglet diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index d20e90b..2b55efd 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -77,8 +77,10 @@ v1d_range_bytes(struct req *req, enum vdp_action act, const void *ptr, l = req->range_high - req->range_off; if (l > len) l = len; - if (act > VDP_NULL || l > 0) + if (l > 0) retval = VDP_bytes(req, act, p, l); + else if (act > VDP_NULL) + retval = VDP_bytes(req, act, p, 0); req->range_off += len; return (retval); } From phk at varnish-cache.org Fri Sep 6 21:50:45 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 23:50:45 +0200 Subject: [master] 065f445 Fix a fine point in this test-case: We can get a Content-Length on a 304 response, but we still don't get the body. Message-ID: commit 065f4457b5a496e74cb5af9e8fbb4fc7e30ab349 Author: Poul-Henning Kamp Date: Fri Sep 6 16:58:54 2013 +0000 Fix a fine point in this test-case: We can get a Content-Length on a 304 response, but we still don't get the body. diff --git a/bin/varnishtest/tests/c00008.vtc b/bin/varnishtest/tests/c00008.vtc index 69c64d4..e41e0b2 100644 --- a/bin/varnishtest/tests/c00008.vtc +++ b/bin/varnishtest/tests/c00008.vtc @@ -25,13 +25,13 @@ client c1 { txreq -url "/foo" \ -hdr "If-Modified-Since: Thu, 26 Jun 2008 12:00:01 GMT" - rxresp + rxresp -no_obj expect resp.status == 304 expect resp.http.etag == "foo" txreq -url "/foo" \ -hdr "If-Modified-Since: Thu, 26 Jun 2008 12:00:02 GMT" - rxresp + rxresp -no_obj expect resp.status == 304 expect resp.http.etag == "foo" } From phk at varnish-cache.org Fri Sep 6 21:50:45 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 23:50:45 +0200 Subject: [master] 50fdfcf Fix other 304 return cases to not expect a body Message-ID: commit 50fdfcfe0565b7cd2f38c2e13b4cc8f44b106334 Author: Poul-Henning Kamp Date: Fri Sep 6 17:20:30 2013 +0000 Fix other 304 return cases to not expect a body diff --git a/bin/varnishtest/tests/c00025.vtc b/bin/varnishtest/tests/c00025.vtc index d0cd83d..4432918 100644 --- a/bin/varnishtest/tests/c00025.vtc +++ b/bin/varnishtest/tests/c00025.vtc @@ -22,7 +22,7 @@ client c1 { txreq -url "/foo" \ -hdr "If-None-Match: 123456789" - rxresp + rxresp -no_obj expect resp.status == 304 } diff --git a/bin/varnishtest/tests/c00026.vtc b/bin/varnishtest/tests/c00026.vtc index 5dcbd41..9f8c168 100644 --- a/bin/varnishtest/tests/c00026.vtc +++ b/bin/varnishtest/tests/c00026.vtc @@ -18,12 +18,12 @@ client c1 { txreq -url "/foo" \ -hdr "If-None-Match: 123456789" - rxresp + rxresp -no_obj expect resp.status == 304 txreq -url "/foo" \ -hdr "If-Modified-Since: Thu, 26 Jun 2008 12:00:01 GMT" - rxresp + rxresp -no_obj expect resp.status == 304 txreq -url "/foo" \ @@ -41,7 +41,7 @@ client c1 { txreq -url "/foo" \ -hdr "If-Modified-Since: Thu, 26 Jun 2008 12:00:01 GMT" \ -hdr "If-None-Match: 123456789" - rxresp + rxresp -no_obj expect resp.status == 304 } diff --git a/bin/varnishtest/tests/r00795.vtc b/bin/varnishtest/tests/r00795.vtc index 2d832aa..0abfc29 100644 --- a/bin/varnishtest/tests/r00795.vtc +++ b/bin/varnishtest/tests/r00795.vtc @@ -1,10 +1,13 @@ varnishtest "Content-Length in pass'ed 304 does not trigger body fetch" +# XXX: Description doesn't make sense relative to actual goings on... + server s1 { rxreq txresp -hdr "Last-Modified: ${date}" -body "FOO" rxreq - txresp -body "FOO" + expect req.url == "/bar" + txresp -body "FOOBAR" } -start @@ -21,7 +24,7 @@ client c1 { txreq -url "/bar" rxresp expect resp.status == 200 - expect resp.bodylen == 3 + expect resp.bodylen == 6 } -run # Wait, so we know ${date} to be higher @@ -29,12 +32,10 @@ delay 1 client c1 { txreq -hdr "If-Modified-Since: ${date}" - rxresp + rxresp -no_obj expect resp.status == 304 - expect resp.bodylen == 0 txreq -url "/bar" -hdr "If-Modified-Since: ${date}" - rxresp + rxresp -no_obj expect resp.status == 304 - expect resp.bodylen == 0 } -run diff --git a/bin/varnishtest/tests/r00803.vtc b/bin/varnishtest/tests/r00803.vtc index 7e47503..50b25fb 100644 --- a/bin/varnishtest/tests/r00803.vtc +++ b/bin/varnishtest/tests/r00803.vtc @@ -15,6 +15,6 @@ varnish v1 -vcl+backend { client c1 { txreq - rxresp + rxresp -no_obj expect resp.status == 304 } -run diff --git a/bin/varnishtest/tests/r00806.vtc b/bin/varnishtest/tests/r00806.vtc index 7e8fdbc..f5ee9e3 100644 --- a/bin/varnishtest/tests/r00806.vtc +++ b/bin/varnishtest/tests/r00806.vtc @@ -20,7 +20,7 @@ varnish v1 -vcl+backend { client c1 { txreq - rxresp + rxresp -no_obj expect resp.status == 304 expect resp.http.cl == 100 } -run diff --git a/bin/varnishtest/tests/r00907.vtc b/bin/varnishtest/tests/r00907.vtc index b64a160..679dab2 100644 --- a/bin/varnishtest/tests/r00907.vtc +++ b/bin/varnishtest/tests/r00907.vtc @@ -15,17 +15,17 @@ varnish v1 -vcl+backend { client c1 { txreq -hdr "If-None-Match: saengei1Ohshicich4iteesu" - rxresp + rxresp -no_obj expect resp.status == 304 txreq -hdr "If-None-Match: saengei1Ohshicich4iteesu" \ -hdr "If-Modified-Since: Tue, 20 Sep 2011 18:54:59 GMT" - rxresp + rxresp -no_obj expect resp.status == 200 txreq -hdr "If-None-Match: saengei1Ohshicich4iteesu" \ -hdr "If-Modified-Since: Tue, 20 Sep 2011 18:55:00 GMT" - rxresp + rxresp -no_obj expect resp.status == 304 } -run diff --git a/bin/varnishtest/tests/r00972.vtc b/bin/varnishtest/tests/r00972.vtc index da23127..d5e0f0e 100644 --- a/bin/varnishtest/tests/r00972.vtc +++ b/bin/varnishtest/tests/r00972.vtc @@ -13,9 +13,8 @@ varnish v1 -vcl+backend { client c1 { txreq -hdr "If-None-Match: foo" - rxresp + rxresp -no_obj expect resp.status == 304 expect resp.http.etag == "foo" - expect resp.bodylen == 0 } -run From phk at varnish-cache.org Fri Sep 6 21:50:45 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 23:50:45 +0200 Subject: [master] 138e67f IMS decision is protocol-independent Message-ID: commit 138e67f6185d943cb0ca8bfa14e018f6a2a62a6f Author: Poul-Henning Kamp Date: Fri Sep 6 17:27:04 2013 +0000 IMS decision is protocol-independent diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index 2b55efd..39b70eb 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -242,13 +242,7 @@ V1D_Deliver(struct req *req) if (req->res_mode & RES_GUNZIP) http_Unset(req->resp, H_Content_Encoding); - if (!(req->obj->objcore->flags & OC_F_PASS) - && req->obj->response == 200 - && req->http->conds && RFC2616_Do_Cond(req)) { - req->wantbody = 0; - http_SetResp(req->resp, "HTTP/1.1", 304, "Not Modified"); - http_Unset(req->resp, H_Content_Length); - } else if (req->res_mode & RES_CHUNKED) + if (req->res_mode & RES_CHUNKED) http_SetHeader(req->resp, "Transfer-Encoding: chunked"); http_SetHeader(req->resp, diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index a50b65c..9e0d35a 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -150,6 +150,14 @@ cnt_deliver(struct worker *wrk, struct req *req) assert(wrk->handling == VCL_RET_DELIVER); + if (!(req->obj->objcore->flags & OC_F_PASS) + && req->obj->response == 200 + && req->http->conds && RFC2616_Do_Cond(req)) { + req->wantbody = 0; + http_SetResp(req->resp, "HTTP/1.1", 304, "Not Modified"); + // http_Unset(req->resp, H_Content_Length); + } + V1D_Deliver(req); /* No point in saving the body if it is hit-for-pass */ From phk at varnish-cache.org Fri Sep 6 21:50:45 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 23:50:45 +0200 Subject: [master] 83c03a8 Single test for Range-qualifying request Message-ID: commit 83c03a89fe6e4c3e591d1bd8cff65a7d8def2f0a Author: Poul-Henning Kamp Date: Fri Sep 6 17:36:51 2013 +0000 Single test for Range-qualifying request diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index 39b70eb..04dab9d 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -202,8 +202,6 @@ V1D_Deliver(struct req *req) http_PrintfHeader(req->resp, "Content-Length: %zd", req->obj->len); } - if (cache_param->http_range_support) - http_SetHeader(req->resp, "Accept-Ranges: bytes"); } if (req->esi_level > 0) { @@ -255,9 +253,11 @@ V1D_Deliver(struct req *req) req->wantbody && !(req->res_mode & (RES_ESI|RES_ESI_CHILD)) && cache_param->http_range_support && - req->obj->response == 200 && - http_GetHdr(req->http, H_Range, &r)) - v1d_dorange(req, r); + req->obj->response == 200) { + http_SetHeader(req->resp, "Accept-Ranges: bytes"); + if (http_GetHdr(req->http, H_Range, &r)) + v1d_dorange(req, r); + } WRW_Reserve(req->wrk, &req->sp->fd, req->vsl, req->t_resp); From phk at varnish-cache.org Fri Sep 6 21:50:45 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 23:50:45 +0200 Subject: [master] d2ed41c Move the stream-stopper all the way to where streaming will happen Message-ID: commit d2ed41c6aaac8ec33811fb36c95e9aaa3048b394 Author: Poul-Henning Kamp Date: Fri Sep 6 20:07:08 2013 +0000 Move the stream-stopper all the way to where streaming will happen diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index 04dab9d..640d94a 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -184,9 +184,6 @@ V1D_Deliver(struct req *req) CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(req->obj->objcore, OBJCORE_MAGIC); - while (req->obj->objcore->busyobj) - (void)usleep(10000); - req->res_mode = 0; if (!req->disable_esi && req->obj->esidata != NULL) { @@ -275,11 +272,12 @@ V1D_Deliver(struct req *req) if (!req->wantbody) { /* This was a HEAD or conditional request */ - } else if (req->obj->len == 0) { - /* Nothing to do here */ } else if (req->res_mode & RES_ESI) { + AZ(req->obj->objcore->busyobj); ESI_Deliver(req); } else if (req->res_mode & RES_ESI_CHILD && req->gzip_resp) { + while (req->obj->objcore->busyobj) + (void)usleep(10000); ESI_DeliverChild(req); } else if (req->res_mode & RES_GUNZIP || (req->res_mode & RES_ESI_CHILD && diff --git a/bin/varnishd/cache/cache_obj.c b/bin/varnishd/cache/cache_obj.c index 65f443b..5b878b9 100644 --- a/bin/varnishd/cache/cache_obj.c +++ b/bin/varnishd/cache/cache_obj.c @@ -46,6 +46,8 @@ ObjIterBegin(struct object *obj) CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC); ALLOC_OBJ(oi, OBJITER_MAGIC); + while (obj->objcore->busyobj != NULL) + usleep(10000); if (oi != NULL) oi->obj = obj; return (oi); From phk at varnish-cache.org Fri Sep 6 21:50:45 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 23:50:45 +0200 Subject: [master] 7f017eb Atomically grab the busyobj, if there is one. Message-ID: commit 7f017ebe826be6b435e98762bd32ee56191cb6fb Author: Poul-Henning Kamp Date: Fri Sep 6 20:31:17 2013 +0000 Atomically grab the busyobj, if there is one. diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index cc2f963..b0747cc 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -1060,7 +1060,7 @@ void *MPL_Get(struct mempool *mpl, unsigned *size); void MPL_Free(struct mempool *mpl, void *item); /* cache_obj.c */ -struct objiter *ObjIterBegin(struct object *); +struct objiter *ObjIterBegin(struct worker *, struct object *); int ObjIter(struct objiter *, void **, ssize_t *); void ObjIterEnd(struct objiter **); diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c index 46ec3ba..7171b53 100644 --- a/bin/varnishd/cache/cache_hash.c +++ b/bin/varnishd/cache/cache_hash.c @@ -712,6 +712,29 @@ HSH_Ref(struct objcore *oc) Lck_Unlock(&oh->mtx); } +/*--------------------------------------------------------------------- + * Gain a reference on the busyobj, if the objcore has one + */ + +struct busyobj * +HSH_RefBusy(const struct objcore *oc) +{ + struct objhead *oh; + struct busyobj *bo; + + CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); + oh = oc->objhead; + CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC); + Lck_Lock(&oh->mtx); + assert(oc->refcnt > 0); + bo = oc->busyobj; + CHECK_OBJ_ORNULL(bo, BUSYOBJ_MAGIC); + if (bo != NULL) + bo->refcount++; + Lck_Unlock(&oh->mtx); + return (bo); +} + /*-------------------------------------------------------------------- * Dereference objcore and or object * diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index 640d94a..1678eb5 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -164,7 +164,7 @@ v1d_WriteDirObj(struct req *req) CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - oi = ObjIterBegin(req->obj); + oi = ObjIterBegin(req->wrk, req->obj); XXXAN(oi); while (ObjIter(oi, &ptr, &len)) { diff --git a/bin/varnishd/cache/cache_obj.c b/bin/varnishd/cache/cache_obj.c index 5b878b9..3db119d 100644 --- a/bin/varnishd/cache/cache_obj.c +++ b/bin/varnishd/cache/cache_obj.c @@ -31,25 +31,31 @@ #include #include "cache.h" +#include "hash/hash_slinger.h" struct objiter { unsigned magic; #define OBJITER_MAGIC 0x745fb151 + struct busyobj *bo; struct object *obj; struct storage *st; + struct worker *wrk; }; struct objiter * -ObjIterBegin(struct object *obj) +ObjIterBegin(struct worker *wrk, struct object *obj) { struct objiter *oi; CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC); ALLOC_OBJ(oi, OBJITER_MAGIC); + if (oi == NULL) + return (oi); + oi->obj = obj; + oi->wrk = wrk; + oi->bo = HSH_RefBusy(obj->objcore); while (obj->objcore->busyobj != NULL) - usleep(10000); - if (oi != NULL) - oi->obj = obj; + (void)usleep(10000); return (oi); } @@ -77,6 +83,10 @@ void ObjIterEnd(struct objiter **oi) { + AN(oi); CHECK_OBJ_NOTNULL((*oi), OBJITER_MAGIC); + if ((*oi)->bo != NULL) + VBO_DerefBusyObj((*oi)->wrk, &(*oi)->bo); FREE_OBJ((*oi)); + *oi = NULL; } diff --git a/bin/varnishd/hash/hash_slinger.h b/bin/varnishd/hash/hash_slinger.h index 152eebd..cbe7082 100644 --- a/bin/varnishd/hash/hash_slinger.h +++ b/bin/varnishd/hash/hash_slinger.h @@ -73,6 +73,7 @@ void HSH_AddString(const struct req *, const char *str); void HSH_Insert(struct worker *, const void *hash, struct objcore *); void HSH_Purge(struct worker *, struct objhead *, double ttl, double grace); void HSH_config(const char *h_arg); +struct busyobj *HSH_RefBusy(const struct objcore *oc); struct objcore *HSH_Private(struct worker *wrk); struct objcore *HSH_NewObjCore(struct worker *wrk); From phk at varnish-cache.org Fri Sep 6 21:50:45 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 06 Sep 2013 23:50:45 +0200 Subject: [master] a6d46e7 Stream. Message-ID: commit a6d46e7debd71be4c5facf4d58220217756da277 Author: Poul-Henning Kamp Date: Fri Sep 6 21:50:01 2013 +0000 Stream. (Don't tell me nothing good ever comes from DB's delayed trains...) diff --git a/bin/varnishd/cache/cache_busyobj.c b/bin/varnishd/cache/cache_busyobj.c index 063c49c..01f0a33 100644 --- a/bin/varnishd/cache/cache_busyobj.c +++ b/bin/varnishd/cache/cache_busyobj.c @@ -228,6 +228,7 @@ ssize_t VBO_waitlen(struct busyobj *bo, ssize_t l) { Lck_Lock(&bo->mtx); + assert(l <= bo->fetch_obj->len); while (1) { if (bo->fetch_obj->len > l || bo->state >= BOS_FINISHED) { l = bo->fetch_obj->len; diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c index 1678eb5..6ed3110 100644 --- a/bin/varnishd/cache/cache_http1_deliver.c +++ b/bin/varnishd/cache/cache_http1_deliver.c @@ -158,6 +158,7 @@ v1d_dorange(struct req *req, const char *r) static void v1d_WriteDirObj(struct req *req) { + int i; ssize_t len; struct objiter *oi; void *ptr; @@ -167,10 +168,12 @@ v1d_WriteDirObj(struct req *req) oi = ObjIterBegin(req->wrk, req->obj); XXXAN(oi); - while (ObjIter(oi, &ptr, &len)) { - if (VDP_bytes(req, VDP_NULL, ptr, len)) - break; - } + do { + i = ObjIter(oi, &ptr, &len); + if (i != 0) + if (VDP_bytes(req, i == 2 ? VDP_FLUSH : VDP_NULL, ptr, len)) + break; + } while (i); (void)VDP_bytes(req, VDP_FINISH, NULL, 0); ObjIterEnd(&oi); } diff --git a/bin/varnishd/cache/cache_http1_fetch.c b/bin/varnishd/cache/cache_http1_fetch.c index e8dbdaa..d15d6c9 100644 --- a/bin/varnishd/cache/cache_http1_fetch.c +++ b/bin/varnishd/cache/cache_http1_fetch.c @@ -381,7 +381,8 @@ V1F_fetch_body(struct worker *wrk, struct busyobj *bo) */ st = VTAILQ_LAST(&bo->fetch_obj->store, storagehead); - if (st != NULL) { + /* XXX: Temporary: Only trim if we are not streaming */ + if (st != NULL && !bo->do_stream) { /* XXX: is any of this safe under streaming ? */ if (st->len == 0) { VTAILQ_REMOVE(&bo->fetch_obj->store, st, list); diff --git a/bin/varnishd/cache/cache_obj.c b/bin/varnishd/cache/cache_obj.c index 3db119d..2ca0a01 100644 --- a/bin/varnishd/cache/cache_obj.c +++ b/bin/varnishd/cache/cache_obj.c @@ -40,6 +40,7 @@ struct objiter { struct object *obj; struct storage *st; struct worker *wrk; + ssize_t len; }; struct objiter * @@ -54,29 +55,49 @@ ObjIterBegin(struct worker *wrk, struct object *obj) oi->obj = obj; oi->wrk = wrk; oi->bo = HSH_RefBusy(obj->objcore); - while (obj->objcore->busyobj != NULL) - (void)usleep(10000); return (oi); } int ObjIter(struct objiter *oi, void **p, ssize_t *l) { + ssize_t ol; + ssize_t nl; CHECK_OBJ_NOTNULL(oi, OBJITER_MAGIC); AN(p); AN(l); - if (oi->st == NULL) - oi->st = VTAILQ_FIRST(&oi->obj->store); - else - oi->st = VTAILQ_NEXT(oi->st, list); - if (oi->st != NULL) { - *p = oi->st->ptr; - *l = oi->st->len; - return (1); + if (oi->bo == NULL) { + if (oi->st == NULL) + oi->st = VTAILQ_FIRST(&oi->obj->store); + else + oi->st = VTAILQ_NEXT(oi->st, list); + if (oi->st != NULL) { + *p = oi->st->ptr; + *l = oi->st->len; + return (1); + } + return (0); + } else { + ol = oi->len; + nl = VBO_waitlen(oi->bo, ol); + VSL(SLT_Debug, 0, "STREAM %zd -> %zd", ol, nl); + if (nl == ol) + return (0); + VTAILQ_FOREACH(oi->st, &oi->obj->store, list) { + if (oi->st->len <= ol) { + ol -= oi->st->len; + nl -= oi->st->len; + } else { + *p = oi->st->ptr + ol; + *l = (nl - ol); + oi->len += (nl - ol); + return (2); + } + } + WRONG("ran off end"); } - return (0); } void diff --git a/bin/varnishtest/tests/b00029.vtc b/bin/varnishtest/tests/b00029.vtc index 8df3997..386e156 100644 --- a/bin/varnishtest/tests/b00029.vtc +++ b/bin/varnishtest/tests/b00029.vtc @@ -3,7 +3,13 @@ varnishtest "Test orderly connection closure" server s1 { rxreq - txresp -bodylen 130000 + txresp -nolen -hdr "Transfer-encoding: chunked" + delay .2 + chunkedlen 30000 + delay .2 + chunkedlen 100000 + delay .2 + chunkedlen 0 } -start varnish v1 -vcl+backend { } -start From phk at varnish-cache.org Sat Sep 7 10:11:57 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Sat, 07 Sep 2013 12:11:57 +0200 Subject: [master] e5eac24 Add a missing #include Message-ID: commit e5eac24b59217e6733678b914c726d9231f73578 Author: Poul-Henning Kamp Date: Sat Sep 7 10:01:56 2013 +0000 Add a missing #include diff --git a/bin/varnishtest/vtc_http.c b/bin/varnishtest/vtc_http.c index 6a204dc..7959b74 100644 --- a/bin/varnishtest/vtc_http.c +++ b/bin/varnishtest/vtc_http.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include "vtc.h" From phk at varnish-cache.org Sat Sep 7 10:11:57 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Sat, 07 Sep 2013 12:11:57 +0200 Subject: [master] 9535e27 Update our copy of ZLIB to 1.2.8 Message-ID: commit 9535e277d839f677f12d1f6b5b510eb927f99047 Author: Poul-Henning Kamp Date: Sat Sep 7 10:11:12 2013 +0000 Update our copy of ZLIB to 1.2.8 diff --git a/lib/libvgz/Makefile.am b/lib/libvgz/Makefile.am index 7497aab..54226bb 100644 --- a/lib/libvgz/Makefile.am +++ b/lib/libvgz/Makefile.am @@ -4,7 +4,7 @@ AM_LDFLAGS = $(AM_LT_LDFLAGS) pkglib_LTLIBRARIES = libvgz.la libvgz_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version -libvgz_la_CFLAGS = -D_LARGEFILE64_SOURCE=1 $(libvgz_extra_cflags) +libvgz_la_CFLAGS = -D_LARGEFILE64_SOURCE=1 -DZLIB_CONST $(libvgz_extra_cflags) libvgz_la_SOURCES = \ adler32.c \ diff --git a/lib/libvgz/README b/lib/libvgz/README index 96df477..9b2fb39 100644 --- a/lib/libvgz/README +++ b/lib/libvgz/README @@ -1,16 +1,117 @@ -This is a modified version of the ZLIB 1.2.5 data compression library. +This is a modified version of the ZLIB 1.2.8 data compression library. -For the original and complete version of the library please visit: +ZLIB DATA COMPRESSION LIBRARY - http://www.zlib.net/ +zlib 1.2.8 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and +rfc1952 (gzip format). -For copyright and licensing information, please see the zlib.h file. +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib at gzip.org). A usage example +of the library is given in the file test/example.c which also tests that +the library is working correctly. Another example is given in the file +test/minigzip.c. The compression library itself is composed of all source +files in the root directory. -Modifications include: +To compile all files and run the test program, follow the instructions given at +the top of Makefile.in. In short "./configure; make test", and if that goes +well, "make install" should work for most flavors of Unix. For Windows, use +one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use +make_vms.com. -* Unnecessary files not imported. +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://zlib.net/ . Before reporting a problem, please check this site to +verify that you have the latest version of zlib; otherwise get the latest +version and check whether the problem still exists or not. -* Extension to inflate() to record the bit positions of: - A) The first deflate block - B) The 'last' bit - C) The first (padding) bit after the last deflate block +PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available at +http://marknelson.us/1997/01/01/zlib-engine/ . + +The changes made in version 1.2.8 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory contrib/ . + +zlib is available in Java using the java.util.zip package, documented at +http://java.sun.com/developer/technicalArticles/Programming/compression/ . + +A Perl interface to zlib written by Paul Marquess is available +at CPAN (Comprehensive Perl Archive Network) sites, including +http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://docs.python.org/library/zlib.html . + +zlib is built into tcl: http://wiki.tcl.tk/4610 . + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS or BEOS. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate and + zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; they + are too numerous to cite here. + +Copyright notice: + + (C) 1995-2013 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup at gzip.org madler at alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. diff --git a/lib/libvgz/adler32.c b/lib/libvgz/adler32.c index 65ad6a5..a868f07 100644 --- a/lib/libvgz/adler32.c +++ b/lib/libvgz/adler32.c @@ -1,5 +1,5 @@ /* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2007 Mark Adler + * Copyright (C) 1995-2011 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,9 +9,9 @@ #define local static -local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); -#define BASE 65521UL /* largest prime smaller than 65536 */ +#define BASE 65521 /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ @@ -21,39 +21,44 @@ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); -/* use NO_DIVIDE if your processor does not do division in hardware */ +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ #ifdef NO_DIVIDE -# define MOD(a) \ +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ + do { \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ do { \ - if (a >= (BASE << 16)) a -= (BASE << 16); \ - if (a >= (BASE << 15)) a -= (BASE << 15); \ - if (a >= (BASE << 14)) a -= (BASE << 14); \ - if (a >= (BASE << 13)) a -= (BASE << 13); \ - if (a >= (BASE << 12)) a -= (BASE << 12); \ - if (a >= (BASE << 11)) a -= (BASE << 11); \ - if (a >= (BASE << 10)) a -= (BASE << 10); \ - if (a >= (BASE << 9)) a -= (BASE << 9); \ - if (a >= (BASE << 8)) a -= (BASE << 8); \ - if (a >= (BASE << 7)) a -= (BASE << 7); \ - if (a >= (BASE << 6)) a -= (BASE << 6); \ - if (a >= (BASE << 5)) a -= (BASE << 5); \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ + CHOP(a); \ if (a >= BASE) a -= BASE; \ } while (0) -# define MOD4(a) \ +# define MOD(a) \ do { \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ if (a >= BASE) a -= BASE; \ } while (0) #else # define MOD(a) a %= BASE -# define MOD4(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE #endif /* ========================================================================= */ @@ -92,7 +97,7 @@ uLong ZEXPORT adler32(adler, buf, len) } if (adler >= BASE) adler -= BASE; - MOD4(sum2); /* only added so many BASE's */ + MOD28(sum2); /* only added so many BASE's */ return adler | (sum2 << 16); } @@ -137,8 +142,13 @@ local uLong adler32_combine_(adler1, adler2, len2) unsigned long sum2; unsigned rem; + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + /* the derivation of this formula is left as an exercise for the reader */ - rem = (unsigned)(len2 % BASE); + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; sum1 = adler1 & 0xffff; sum2 = rem * sum1; MOD(sum2); diff --git a/lib/libvgz/compress.c b/lib/libvgz/compress.c index b369014..114fdb1 100644 --- a/lib/libvgz/compress.c +++ b/lib/libvgz/compress.c @@ -29,7 +29,7 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) z_stream stream; int err; - stream.next_in = (Bytef*)(uintptr_t)source; + stream.next_in = (z_const Bytef *)source; stream.avail_in = (uInt)sourceLen; #ifdef MAXSEG_64K /* Check for source > 64K on 16-bit machine: */ diff --git a/lib/libvgz/crc32.c b/lib/libvgz/crc32.c index 91be372..979a719 100644 --- a/lib/libvgz/crc32.c +++ b/lib/libvgz/crc32.c @@ -1,5 +1,5 @@ /* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010 Mark Adler + * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster @@ -17,6 +17,8 @@ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should first call get_crc_table() to initialize the tables before allowing more than one thread to use crc32(). + + DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. */ #ifdef MAKECRCH @@ -30,31 +32,11 @@ #define local static -/* Find a four-byte integer type for crc32_little() and crc32_big(). */ -#ifndef NOBYFOUR -# ifdef STDC /* need ANSI C limits.h to determine sizes */ -# include -# define BYFOUR -# if (UINT_MAX == 0xffffffffUL) - typedef unsigned int u4; -# else -# if (ULONG_MAX == 0xffffffffUL) - typedef unsigned long u4; -# else -# if (USHRT_MAX == 0xffffffffUL) - typedef unsigned short u4; -# else -# undef BYFOUR /* can't find a four-byte integer type! */ -# endif -# endif -# endif -# endif /* STDC */ -#endif /* !NOBYFOUR */ - /* Definitions for doing the crc four data bytes at a time. */ +#if !defined(NOBYFOUR) && defined(Z_U4) +# define BYFOUR +#endif #ifdef BYFOUR -# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ - (((w)&0xff00)<<8)+(((w)&0xff)<<24)) local unsigned long crc32_little OF((unsigned long, const unsigned char FAR *, unsigned)); local unsigned long crc32_big OF((unsigned long, @@ -68,16 +50,16 @@ local unsigned long gf2_matrix_times OF((unsigned long *mat, unsigned long vec)); local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); -local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); +local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); #ifdef DYNAMIC_CRC_TABLE local volatile int crc_table_empty = 1; -local unsigned long FAR crc_table[TBLS][256]; +local z_crc_t FAR crc_table[TBLS][256]; local void make_crc_table OF((void)); #ifdef MAKECRCH - local void write_table OF((FILE *, const unsigned long FAR *)); + local void write_table OF((FILE *, const z_crc_t FAR *)); #endif /* MAKECRCH */ /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: @@ -107,9 +89,9 @@ local void make_crc_table OF((void)); */ local void make_crc_table() { - unsigned long c; + z_crc_t c; int n, k; - unsigned long poly; /* polynomial exclusive-or pattern */ + z_crc_t poly; /* polynomial exclusive-or pattern */ /* terms of polynomial defining this crc (except x^32): */ static volatile int first = 1; /* flag to limit concurrent making */ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; @@ -121,13 +103,13 @@ local void make_crc_table() first = 0; /* make exclusive-or pattern from polynomial (0xedb88320UL) */ - poly = 0UL; - for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) - poly |= 1UL << (31 - p[n]); + poly = 0; + for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) + poly |= (z_crc_t)1 << (31 - p[n]); /* generate a crc for every 8-bit value */ for (n = 0; n < 256; n++) { - c = (unsigned long)n; + c = (z_crc_t)n; for (k = 0; k < 8; k++) c = c & 1 ? poly ^ (c >> 1) : c >> 1; crc_table[0][n] = c; @@ -138,11 +120,11 @@ local void make_crc_table() and then the byte reversal of those as well as the first table */ for (n = 0; n < 256; n++) { c = crc_table[0][n]; - crc_table[4][n] = REV(c); + crc_table[4][n] = ZSWAP32(c); for (k = 1; k < 4; k++) { c = crc_table[0][c & 0xff] ^ (c >> 8); crc_table[k][n] = c; - crc_table[k + 4][n] = REV(c); + crc_table[k + 4][n] = ZSWAP32(c); } } #endif /* BYFOUR */ @@ -164,7 +146,7 @@ local void make_crc_table() if (out == NULL) return; fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); - fprintf(out, "local const unsigned long FAR "); + fprintf(out, "local const z_crc_t FAR "); fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); write_table(out, crc_table[0]); # ifdef BYFOUR @@ -184,12 +166,13 @@ local void make_crc_table() #ifdef MAKECRCH local void write_table(out, table) FILE *out; - const unsigned long FAR *table; + const z_crc_t FAR *table; { int n; for (n = 0; n < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", + (unsigned long)(table[n]), n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); } #endif /* MAKECRCH */ @@ -204,13 +187,13 @@ local void write_table(out, table) /* ========================================================================= * This function can be used by asm versions of crc32() */ -const unsigned long FAR * ZEXPORT get_crc_table() +const z_crc_t FAR * ZEXPORT get_crc_table() { #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ - return (const unsigned long FAR *)crc_table; + return (const z_crc_t FAR *)crc_table; } /* ========================================================================= */ @@ -232,7 +215,7 @@ unsigned long ZEXPORT crc32(crc, buf, len) #ifdef BYFOUR if (sizeof(void *) == sizeof(ptrdiff_t)) { - u4 endian; + z_crc_t endian; endian = 1; if (*((unsigned char *)(&endian))) @@ -266,17 +249,17 @@ local unsigned long crc32_little(crc, buf, len) const unsigned char FAR *buf; unsigned len; { - register u4 c; - register const u4 FAR *buf4; + register z_crc_t c; + register const z_crc_t FAR *buf4; - c = (u4)crc; + c = (z_crc_t)crc; c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); len--; } - buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; while (len >= 32) { DOLIT32; len -= 32; @@ -306,17 +289,17 @@ local unsigned long crc32_big(crc, buf, len) const unsigned char FAR *buf; unsigned len; { - register u4 c; - register const u4 FAR *buf4; + register z_crc_t c; + register const z_crc_t FAR *buf4; - c = REV((u4)crc); + c = ZSWAP32((z_crc_t)crc); c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); len--; } - buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; buf4--; while (len >= 32) { DOBIG32; @@ -333,7 +316,7 @@ local unsigned long crc32_big(crc, buf, len) c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); } while (--len); c = ~c; - return (unsigned long)(REV(c)); + return (unsigned long)(ZSWAP32(c)); } #endif /* BYFOUR */ diff --git a/lib/libvgz/crc32.h b/lib/libvgz/crc32.h index 8053b61..9e0c778 100644 --- a/lib/libvgz/crc32.h +++ b/lib/libvgz/crc32.h @@ -2,7 +2,7 @@ * Generated automatically by crc32.c */ -local const unsigned long FAR crc_table[TBLS][256] = +local const z_crc_t FAR crc_table[TBLS][256] = { { 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, diff --git a/lib/libvgz/deflate.c b/lib/libvgz/deflate.c index f74c6ca..f6de44a 100644 --- a/lib/libvgz/deflate.c +++ b/lib/libvgz/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -37,7 +37,7 @@ * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://www.ietf.org/rfc/rfc1951.txt + * Available in http://tools.ietf.org/html/rfc1951 * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; + " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -155,6 +155,9 @@ local const config configuration_table[10] = { struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ #endif +/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ +#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) + /* =========================================================================== * Update a hash value with the given input byte * IN assertion: all calls to to UPDATE_HASH are made with consecutive @@ -235,10 +238,19 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, strm->msg = Z_NULL; if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; +#endif } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif #ifdef FASTEST if (level != 0) level = 1; @@ -314,43 +326,70 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) uInt dictLength; { deflate_state *s; - uInt length = dictLength; - uInt n; - IPos hash_head = 0; + uInt str, n; + int wrap; + unsigned avail; + z_const unsigned char *next; - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || - strm->state->wrap == 2 || - (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - if (s->wrap) - strm->adler = adler32(strm->adler, dictionary, dictLength); + wrap = s->wrap; + if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) + return Z_STREAM_ERROR; - if (length < MIN_MATCH) return Z_OK; - if (length > s->w_size) { - length = s->w_size; - dictionary += dictLength - length; /* use the tail of the dictionary */ + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap == 1) + strm->adler = adler32(strm->adler, dictionary, dictLength); + s->wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s->w_size) { + if (wrap == 0) { /* already empty otherwise */ + CLEAR_HASH(s); + s->strstart = 0; + s->block_start = 0L; + s->insert = 0; + } + dictionary += dictLength - s->w_size; /* use the tail */ + dictLength = s->w_size; } - zmemcpy(s->window, dictionary, length); - s->strstart = length; - s->block_start = (long)length; - /* Insert all strings in the hash table (except for the last two bytes). - * s->lookahead stays null, so s->ins_h will be recomputed at the next - * call of fill_window. - */ - s->ins_h = s->window[0]; - UPDATE_HASH(s, s->ins_h, s->window[1]); - for (n = 0; n <= length - MIN_MATCH; n++) { - INSERT_STRING(s, n, hash_head); + /* insert dictionary into window and hash */ + avail = strm->avail_in; + next = strm->next_in; + strm->avail_in = dictLength; + strm->next_in = (z_const Bytef *)dictionary; + fill_window(s); + while (s->lookahead >= MIN_MATCH) { + str = s->strstart; + n = s->lookahead - (MIN_MATCH-1); + do { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + } while (--n); + s->strstart = str; + s->lookahead = MIN_MATCH-1; + fill_window(s); } - if (hash_head) hash_head = 0; /* to make compiler happy */ + s->strstart += s->lookahead; + s->block_start = (long)s->strstart; + s->insert = s->lookahead; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + strm->next_in = next; + strm->avail_in = avail; + s->wrap = wrap; return Z_OK; } /* ========================================================================= */ -int ZEXPORT deflateReset (strm) +int ZEXPORT deflateResetKeep (strm) z_streamp strm; { deflate_state *s; @@ -381,12 +420,23 @@ int ZEXPORT deflateReset (strm) s->last_flush = Z_NO_FLUSH; _tr_init(s); - lm_init(s); return Z_OK; } /* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + int ret; + + ret = deflateResetKeep(strm); + if (ret == Z_OK) + lm_init(strm->state); + return ret; +} + +/* ========================================================================= */ int ZEXPORT deflateSetHeader (strm, head) z_streamp strm; gz_headerp head; @@ -398,14 +448,42 @@ int ZEXPORT deflateSetHeader (strm, head) } /* ========================================================================= */ +int ZEXPORT deflatePending (strm, pending, bits) + unsigned *pending; + int *bits; + z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (pending != Z_NULL) + *pending = strm->state->pending; + if (bits != Z_NULL) + *bits = strm->state->bi_valid; + return Z_OK; +} + +/* ========================================================================= */ int ZEXPORT deflatePrime (strm, bits, value) z_streamp strm; int bits; int value; { + deflate_state *s; + int put; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - strm->state->bi_valid = bits; - strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + s = strm->state; + if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) + return Z_BUF_ERROR; + do { + put = Buf_size - s->bi_valid; + if (put > bits) + put = bits; + s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); + s->bi_valid += put; + _tr_flush_bits(s); + value >>= put; + bits -= put; + } while (bits); return Z_OK; } @@ -436,6 +514,8 @@ int ZEXPORT deflateParams(strm, level, strategy) strm->total_in != 0) { /* Flush the last buffer: */ err = deflate(strm, Z_BLOCK); + if (err == Z_BUF_ERROR && s->pending == 0) + err = Z_OK; } if (s->level != level) { s->level = level; @@ -563,19 +643,22 @@ local void putShortMSB (s, b) local void flush_pending(strm) z_streamp strm; { - unsigned len = strm->state->pending; + unsigned len; + deflate_state *s = strm->state; + _tr_flush_bits(s); + len = s->pending; if (len > strm->avail_out) len = strm->avail_out; if (len == 0) return; - zmemcpy(strm->next_out, strm->state->pending_out, len); + zmemcpy(strm->next_out, s->pending_out, len); strm->next_out += len; - strm->state->pending_out += len; + s->pending_out += len; strm->total_out += len; strm->avail_out -= len; - strm->state->pending -= len; - if (strm->state->pending == 0) { - strm->state->pending_out = strm->state->pending_buf; + s->pending -= len; + if (s->pending == 0) { + s->pending_out = s->pending_buf; } } @@ -802,7 +885,7 @@ int ZEXPORT deflate (strm, flush) * flushes. For repeated and useless calls with Z_FINISH, we keep * returning Z_STREAM_END instead of Z_BUF_ERROR. */ - } else if (strm->avail_in == 0 && flush <= old_flush && + } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && flush != Z_FINISH) { ERR_RETURN(strm, Z_BUF_ERROR); } @@ -813,7 +896,7 @@ int ZEXPORT deflate (strm, flush) } if (strm->start_bit == 0) - strm->start_bit = (strm->total_out + s->pending) * 8 + s->bi_valid; + strm->start_bit = (strm->total_out + s->pending) * 8 + s->bi_valid; /* Start a new block or continue the current one. */ @@ -854,6 +937,7 @@ int ZEXPORT deflate (strm, flush) if (s->lookahead == 0) { s->strstart = 0; s->block_start = 0L; + s->insert = 0; } } } @@ -949,12 +1033,12 @@ int ZEXPORT deflateCopy (dest, source) ss = source->state; - zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; dest->state = (struct internal_state FAR *) ds; - zmemcpy(ds, ss, sizeof(deflate_state)); + zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); @@ -970,8 +1054,8 @@ int ZEXPORT deflateCopy (dest, source) } /* following zmemcpy do not work for 16-bit MSDOS */ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); @@ -1005,15 +1089,15 @@ local int read_buf(strm, buf, size) strm->avail_in -= len; + zmemcpy(buf, strm->next_in, len); if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, strm->next_in, len); + strm->adler = adler32(strm->adler, buf, len); } #ifdef GZIP else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, strm->next_in, len); + strm->adler = crc32(strm->adler, buf, len); } #endif - zmemcpy(buf, strm->next_in, len); strm->next_in += len; strm->total_in += len; @@ -1040,6 +1124,7 @@ local void lm_init (s) s->strstart = 0; s->block_start = 0L; s->lookahead = 0; + s->insert = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; @@ -1314,6 +1399,8 @@ local void fill_window(s) unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; + Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + do { more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); @@ -1366,7 +1453,7 @@ local void fill_window(s) #endif more += wsize; } - if (s->strm->avail_in == 0) return; + if (s->strm->avail_in == 0) break; /* If there was no sliding: * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && @@ -1385,12 +1472,24 @@ local void fill_window(s) s->lookahead += n; /* Initialize the hash value now that we have some input: */ - if (s->lookahead >= MIN_MATCH) { - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); + if (s->lookahead + s->insert >= MIN_MATCH) { + uInt str = s->strstart - s->insert; + s->ins_h = s->window[str]; + UPDATE_HASH(s, s->ins_h, s->window[str + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif + while (s->insert) { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + s->insert--; + if (s->lookahead + s->insert < MIN_MATCH) + break; + } } /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. @@ -1431,6 +1530,9 @@ local void fill_window(s) s->high_water += init; } } + + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "not enough room for search"); } /* =========================================================================== @@ -1510,8 +1612,14 @@ local block_state deflate_stored(s, flush) FLUSH_BLOCK(s, 0); } } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if ((long)s->strstart > s->block_start) + FLUSH_BLOCK(s, 0); + return block_done; } /* =========================================================================== @@ -1607,8 +1715,14 @@ local block_state deflate_fast(s, flush) } if (bflush) FLUSH_BLOCK(s, 0); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; } #ifndef FASTEST @@ -1732,8 +1846,14 @@ local block_state deflate_slow(s, flush) _tr_tally_lit(s, s->window[s->strstart-1], bflush); s->match_available = 0; } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; } #endif /* FASTEST */ @@ -1753,11 +1873,11 @@ local block_state deflate_rle(s, flush) for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes - * for the longest encodable run. + * for the longest run, plus one for the unrolled loop. */ - if (s->lookahead < MAX_MATCH) { + if (s->lookahead <= MAX_MATCH) { fill_window(s); - if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ @@ -1780,6 +1900,7 @@ local block_state deflate_rle(s, flush) if (s->match_length > s->lookahead) s->match_length = s->lookahead; } + Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ @@ -1800,8 +1921,14 @@ local block_state deflate_rle(s, flush) } if (bflush) FLUSH_BLOCK(s, 0); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; } /* =========================================================================== @@ -1833,6 +1960,12 @@ local block_state deflate_huff(s, flush) s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; } diff --git a/lib/libvgz/deflate.h b/lib/libvgz/deflate.h index cbf0d1e..ce0299e 100644 --- a/lib/libvgz/deflate.h +++ b/lib/libvgz/deflate.h @@ -1,5 +1,5 @@ /* deflate.h -- internal compression state - * Copyright (C) 1995-2010 Jean-loup Gailly + * Copyright (C) 1995-2012 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -48,6 +48,9 @@ #define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ +#define Buf_size 16 +/* size of bit buffer in bi_buf */ + #define INIT_STATE 42 #define EXTRA_STATE 69 #define NAME_STATE 73 @@ -101,7 +104,7 @@ typedef struct internal_state { int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ uInt gzindex; /* where in extra, name, or comment */ - Byte method; /* STORED (for zip only) or DEFLATED */ + Byte method; /* can only be DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ @@ -188,7 +191,7 @@ typedef struct internal_state { int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ - /* Didn't use ct_data typedef below to supress compiler warning */ + /* Didn't use ct_data typedef below to suppress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ @@ -244,7 +247,7 @@ typedef struct internal_state { ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ uInt matches; /* number of string matches in current block */ - int last_eob_len; /* bit length of EOB code for last block */ + uInt insert; /* bytes at end of window left to insert */ #ifdef DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ @@ -294,6 +297,7 @@ void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, int last)); diff --git a/lib/libvgz/gzguts.h b/lib/libvgz/gzguts.h new file mode 100644 index 0000000..53e5aa0 --- /dev/null +++ b/lib/libvgz/gzguts.h @@ -0,0 +1,209 @@ +/* gzguts.h -- zlib internal header definitions for gz* operations + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef _LARGEFILE64_SOURCE +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# endif +# ifdef _FILE_OFFSET_BITS +# undef _FILE_OFFSET_BITS +# endif +#endif + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include +#include "vgz.h" +#ifdef STDC +# include +# include +# include +#endif +#include + +#ifdef _WIN32 +# include +#endif + +#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) +# include +#endif + +#ifdef WINAPI_FAMILY +# define open _open +# define read _read +# define write _write +# define close _close +#endif + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS +/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 +/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +# ifdef VMS +# define NO_vsnprintf +# endif +# ifdef __OS400__ +# define NO_vsnprintf +# endif +# ifdef __MVS__ +# define NO_vsnprintf +# endif +#endif + +/* unlike snprintf (which is required in C99, yet still not supported by + Microsoft more than a decade later!), _snprintf does not guarantee null + termination of the result -- however this is only used in gzlib.c where + the result is assured to fit in the space provided */ +#ifdef _MSC_VER +# define snprintf _snprintf +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +/* gz* functions always use library allocation functions */ +#ifndef STDC + extern voidp malloc OF((uInt size)); + extern void free OF((voidpf ptr)); +#endif + +/* get errno and strerror definition */ +#if defined UNDER_CE +# include +# define zstrerror() gz_strwinerror((DWORD)GetLastError()) +#else +# ifndef NO_STRERROR +# include +# define zstrerror() strerror(errno) +# else +# define zstrerror() "stdio error (consult errno)" +# endif +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); +#endif + +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +/* default i/o buffer size -- double this for output when reading (this and + twice this must be able to fit in an unsigned type) */ +#define GZBUFSIZE 8192 + +/* gzip modes, also provide a little integrity check on the passed structure */ +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ + +/* values for gz_state how */ +#define LOOK 0 /* look for a gzip header */ +#define COPY 1 /* copy input directly */ +#define GZIP 2 /* decompress a gzip stream */ + +/* internal gzip file state data structure */ +typedef struct { + /* exposed contents for gzgetc() macro */ + struct gzFile_s x; /* "x" for exposed */ + /* x.have: number of bytes available at x.next */ + /* x.next: next output data to deliver or write */ + /* x.pos: current position in uncompressed data */ + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + unsigned char *in; /* input buffer */ + unsigned char *out; /* output buffer (double-sized when reading) */ + int direct; /* 0 if processing gzip, 1 if transparent */ + /* just for reading */ + int how; /* 0: get header, 1: copy, 2: decompress */ + z_off64_t start; /* where the gzip data started, for rewinding */ + int eof; /* true if end of input file reached */ + int past; /* true if read requested past end */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + z_stream strm; /* stream structure in-place (not a pointer) */ +} gz_state; +typedef gz_state FAR *gz_statep; + +/* shared functions */ +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +#if defined UNDER_CE +char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +#endif + +/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t + value -- needed when comparing unsigned to z_off64_t, which is signed + (possible z_off64_t types off_t, off64_t, and long are all signed) */ +#ifdef INT_MAX +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) +#else +unsigned ZLIB_INTERNAL gz_intmax OF((void)); +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) +#endif diff --git a/lib/libvgz/infback.c b/lib/libvgz/infback.c index d3af70a..f3833c2 100644 --- a/lib/libvgz/infback.c +++ b/lib/libvgz/infback.c @@ -1,5 +1,5 @@ /* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2009 Mark Adler + * Copyright (C) 1995-2011 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -42,10 +42,19 @@ int stream_size; return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; +#endif } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif state = (struct inflate_state FAR *)ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; @@ -246,7 +255,7 @@ out_func out; void FAR *out_desc; { struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ + z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ @@ -308,7 +317,7 @@ void FAR *out_desc; state->mode = TABLE; break; case 3: - strm->msg = "invalid block type"; + strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); @@ -319,7 +328,7 @@ void FAR *out_desc; BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = "invalid stored block lengths"; + strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } @@ -357,7 +366,7 @@ void FAR *out_desc; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { - strm->msg = "too many length or distance symbols"; + strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } @@ -379,7 +388,7 @@ void FAR *out_desc; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = "invalid code lengths set"; + strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } @@ -394,7 +403,6 @@ void FAR *out_desc; PULLBYTE(); } if (here.val < 16) { - NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } @@ -403,7 +411,7 @@ void FAR *out_desc; NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { - strm->msg = "invalid bit length repeat"; + strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } @@ -426,7 +434,7 @@ void FAR *out_desc; DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { - strm->msg = "invalid bit length repeat"; + strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } @@ -440,7 +448,7 @@ void FAR *out_desc; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { - strm->msg = "invalid code -- missing end-of-block"; + strm->msg = (char *)"invalid code -- missing end-of-block"; state->mode = BAD; break; } @@ -454,7 +462,7 @@ void FAR *out_desc; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = "invalid literal/lengths set"; + strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } @@ -463,7 +471,7 @@ void FAR *out_desc; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { - strm->msg = "invalid distances set"; + strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } @@ -521,7 +529,7 @@ void FAR *out_desc; /* invalid code */ if (here.op & 64) { - strm->msg = "invalid literal/length code"; + strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } @@ -553,7 +561,7 @@ void FAR *out_desc; } DROPBITS(here.bits); if (here.op & 64) { - strm->msg = "invalid distance code"; + strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } @@ -568,7 +576,7 @@ void FAR *out_desc; } if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) { - strm->msg = "invalid distance too far back"; + strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } diff --git a/lib/libvgz/inffast.c b/lib/libvgz/inffast.c index d6b4419..bda59ce 100644 --- a/lib/libvgz/inffast.c +++ b/lib/libvgz/inffast.c @@ -1,5 +1,5 @@ /* inffast.c -- fast decoding - * Copyright (C) 1995-2008, 2010 Mark Adler + * Copyright (C) 1995-2008, 2010, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -69,8 +69,8 @@ z_streamp strm; unsigned start; /* inflate()'s starting value for strm->avail_out */ { struct inflate_state FAR *state; - unsigned char FAR *in; /* local strm->next_in */ - unsigned char FAR *last; /* while in < last, enough input available */ + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ @@ -175,7 +175,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ dist += (unsigned)hold & ((1U << op) - 1); #ifdef INFLATE_STRICT if (dist > dmax) { - strm->msg = "invalid distance too far back"; + strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } @@ -188,7 +188,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ op = dist - op; /* distance back in window */ if (op > whave) { if (state->sane) { - strm->msg = "invalid distance too far back"; + strm->msg = + (char *)"invalid distance too far back"; state->mode = BAD; break; } @@ -284,7 +285,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ goto dodist; } else { - strm->msg = "invalid distance code"; + strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } @@ -299,7 +300,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ break; } else { - strm->msg = "invalid literal/length code"; + strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } diff --git a/lib/libvgz/inffixed.h b/lib/libvgz/inffixed.h index 75ed4b5..d628327 100644 --- a/lib/libvgz/inffixed.h +++ b/lib/libvgz/inffixed.h @@ -2,9 +2,9 @@ * Generated automatically by makefixed(). */ - /* WARNING: this file should *not* be used by applications. It - is part of the implementation of the compression library and - is subject to change. Applications should only use zlib.h. + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. */ static const code lenfix[512] = { diff --git a/lib/libvgz/inflate.c b/lib/libvgz/inflate.c index 0abb681..11f7207 100644 --- a/lib/libvgz/inflate.c +++ b/lib/libvgz/inflate.c @@ -1,5 +1,5 @@ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2010 Mark Adler + * Copyright (C) 1995-2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -93,14 +93,15 @@ /* function prototypes */ local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, unsigned out)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); #ifdef BUILDFIXED void makefixed OF((void)); #endif -local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, unsigned len)); -int ZEXPORT inflateReset(strm) +int ZEXPORT inflateResetKeep(strm) z_streamp strm; { struct inflate_state FAR *state; @@ -110,15 +111,13 @@ z_streamp strm; strm->total_in = strm->total_out = state->total = 0; strm->start_bit = strm->stop_bit = strm->last_bit = 0; strm->msg = Z_NULL; - strm->adler = 1; /* to support ill-conceived Java test suite */ + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; state->mode = HEAD; state->last = 0; state->havedict = 0; state->dmax = 32768U; state->head = Z_NULL; - state->wsize = 0; - state->whave = 0; - state->wnext = 0; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; @@ -128,6 +127,19 @@ z_streamp strm; return Z_OK; } +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + int ZEXPORT inflateReset2(strm, windowBits) z_streamp strm; int windowBits; @@ -181,10 +193,19 @@ int stream_size; if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; +#endif } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif state = (struct inflate_state FAR *) ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; @@ -322,8 +343,8 @@ void makefixed() low = 0; for (;;) { if ((low % 7) == 0) printf("\n "); - printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, - state.lencode[low].val); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); if (++low == size) break; putchar(','); } @@ -356,12 +377,13 @@ void makefixed() output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ -local int updatewindow(strm, out) +local int updatewindow(strm, end, copy) z_streamp strm; -unsigned out; +const Bytef *end; +unsigned copy; { struct inflate_state FAR *state; - unsigned copy, dist; + unsigned dist; state = (struct inflate_state FAR *)strm->state; @@ -381,19 +403,18 @@ unsigned out; } /* copy state->wsize or less output bytes into the circular window */ - copy = out - strm->avail_out; if (copy >= state->wsize) { - zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + zmemcpy(state->window, end - state->wsize, state->wsize); state->wnext = 0; state->whave = state->wsize; } else { dist = state->wsize - state->wnext; if (dist > copy) dist = copy; - zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + zmemcpy(state->window + state->wnext, end - copy, dist); copy -= dist; if (copy) { - zmemcpy(state->window, strm->next_out - copy, copy); + zmemcpy(state->window, end - copy, copy); state->wnext = copy; state->whave = state->wsize; } @@ -500,11 +521,6 @@ unsigned out; bits -= bits & 7; \ } while (0) -/* Reverse the bytes in a 32-bit value */ -#define REVERSE(q) \ - ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - /* inflate() uses a state machine to process as much input data and generate as much output data as possible before returning. The state machine is @@ -592,7 +608,7 @@ z_streamp strm; int flush; { struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ + z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ @@ -644,12 +660,12 @@ int flush; if ( #endif ((BITS(8) << 8) + (hold >> 8)) % 31) { - strm->msg = "incorrect header check"; + strm->msg = (char *)"incorrect header check"; state->mode = BAD; break; } if (BITS(4) != Z_DEFLATED) { - strm->msg = "unknown compression method"; + strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } @@ -658,7 +674,7 @@ int flush; if (state->wbits == 0) state->wbits = len; else if (len > state->wbits) { - strm->msg = "invalid window size"; + strm->msg = (char *)"invalid window size"; state->mode = BAD; break; } @@ -673,12 +689,12 @@ int flush; NEEDBITS(16); state->flags = (int)(hold); if ((state->flags & 0xff) != Z_DEFLATED) { - strm->msg = "unknown compression method"; + strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } if (state->flags & 0xe000) { - strm->msg = "unknown header flags set"; + strm->msg = (char *)"unknown header flags set"; state->mode = BAD; break; } @@ -782,7 +798,7 @@ int flush; if (state->flags & 0x0200) { NEEDBITS(16); if (hold != (state->check & 0xffff)) { - strm->msg = "header crc mismatch"; + strm->msg = (char *)"header crc mismatch"; state->mode = BAD; break; } @@ -798,7 +814,7 @@ int flush; #endif case DICTID: NEEDBITS(32); - strm->adler = state->check = REVERSE(hold); + strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; case DICT: @@ -821,7 +837,7 @@ int flush; } NEEDBITS(3); state->last = BITS(1); - if (state->last) + if (state->last) strm->last_bit = 8 * (strm->total_in + in - have) - bits; DROPBITS(1); switch (BITS(2)) { @@ -846,7 +862,7 @@ int flush; state->mode = TABLE; break; case 3: - strm->msg = "invalid block type"; + strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); @@ -855,7 +871,7 @@ int flush; BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = "invalid stored block lengths"; + strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } @@ -894,7 +910,7 @@ int flush; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { - strm->msg = "too many length or distance symbols"; + strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } @@ -911,12 +927,12 @@ int flush; while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; - state->lencode = (code const FAR *)(state->next); + state->lencode = (const code FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = "invalid code lengths set"; + strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } @@ -931,7 +947,6 @@ int flush; PULLBYTE(); } if (here.val < 16) { - NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } @@ -940,7 +955,7 @@ int flush; NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { - strm->msg = "invalid bit length repeat"; + strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } @@ -963,7 +978,7 @@ int flush; DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { - strm->msg = "invalid bit length repeat"; + strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } @@ -977,7 +992,7 @@ int flush; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { - strm->msg = "invalid code -- missing end-of-block"; + strm->msg = (char *)"invalid code -- missing end-of-block"; state->mode = BAD; break; } @@ -986,21 +1001,21 @@ int flush; values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; - state->lencode = (code const FAR *)(state->next); + state->lencode = (const code FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = "invalid literal/lengths set"; + strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } - state->distcode = (code const FAR *)(state->next); + state->distcode = (const code FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { - strm->msg = "invalid distances set"; + strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } @@ -1052,7 +1067,7 @@ int flush; break; } if (here.op & 64) { - strm->msg = "invalid literal/length code"; + strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } @@ -1088,7 +1103,7 @@ int flush; DROPBITS(here.bits); state->back += here.bits; if (here.op & 64) { - strm->msg = "invalid distance code"; + strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } @@ -1104,7 +1119,7 @@ int flush; } #ifdef INFLATE_STRICT if (state->offset > state->dmax) { - strm->msg = "invalid distance too far back"; + strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } @@ -1118,7 +1133,7 @@ int flush; copy = state->offset - copy; if (copy > state->whave) { if (state->sane) { - strm->msg = "invalid distance too far back"; + strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } @@ -1176,8 +1191,8 @@ int flush; #ifdef GUNZIP state->flags ? hold : #endif - REVERSE(hold)) != state->check) { - strm->msg = "incorrect data check"; + ZSWAP32(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; state->mode = BAD; break; } @@ -1190,7 +1205,7 @@ int flush; if (state->wrap && state->flags) { NEEDBITS(32); if (hold != (state->total & 0xffffffffUL)) { - strm->msg = "incorrect length check"; + strm->msg = (char *)"incorrect length check"; state->mode = BAD; break; } @@ -1220,8 +1235,9 @@ int flush; */ inf_leave: RESTORE(); - if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) - if (updatewindow(strm, out)) { + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { state->mode = MEM; return Z_MEM_ERROR; } @@ -1255,13 +1271,37 @@ z_streamp strm; return Z_OK; } +int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) +z_streamp strm; +Bytef *dictionary; +uInt *dictLength; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; { struct inflate_state FAR *state; - unsigned long id; + unsigned long dictid; + int ret; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; @@ -1269,29 +1309,21 @@ uInt dictLength; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; - /* check for correct dictionary id */ + /* check for correct dictionary identifier */ if (state->mode == DICT) { - id = adler32(0L, Z_NULL, 0); - id = adler32(id, dictionary, dictLength); - if (id != state->check) + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) return Z_DATA_ERROR; } - /* copy dictionary to window */ - if (updatewindow(strm, strm->avail_out)) { + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { state->mode = MEM; return Z_MEM_ERROR; } - if (dictLength > state->wsize) { - zmemcpy(state->window, dictionary + dictLength - state->wsize, - state->wsize); - state->whave = state->wsize; - } - else { - zmemcpy(state->window + state->wsize - dictLength, dictionary, - dictLength); - state->whave = dictLength; - } state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; @@ -1327,7 +1359,7 @@ gz_headerp head; */ local unsigned syncsearch(have, buf, len) unsigned FAR *have; -unsigned char FAR *buf; +const unsigned char FAR *buf; unsigned len; { unsigned got; @@ -1439,8 +1471,8 @@ z_streamp source; } /* copy state */ - zmemcpy(dest, source, sizeof(z_stream)); - zmemcpy(copy, state, sizeof(struct inflate_state)); + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); diff --git a/lib/libvgz/inftrees.c b/lib/libvgz/inftrees.c index 11e9c52..44d89cf 100644 --- a/lib/libvgz/inftrees.c +++ b/lib/libvgz/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2010 Mark Adler + * Copyright (C) 1995-2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; + " inflate 1.2.8 Copyright 1995-2013 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -62,7 +62,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, @@ -208,8 +208,8 @@ unsigned short FAR *work; mask = used - 1; /* mask for comparing low */ /* check available table space */ - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) return 1; /* process all codes and make table entries */ @@ -277,8 +277,8 @@ unsigned short FAR *work; /* check for enough space */ used += 1U << curr; - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) return 1; /* point entry in root table to sub-table */ @@ -289,38 +289,14 @@ unsigned short FAR *work; } } - /* - Fill in rest of table for incomplete codes. This loop is similar to the - loop above in incrementing huff for table indices. It is assumed that - len is equal to curr + drop, so there is no loop needed to increment - through high index bits. When the current sub-table is filled, the loop - drops back to the root table to fill in any remaining entries there. - */ - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)(len - drop); - here.val = (unsigned short)0; - while (huff != 0) { - /* when done with sub-table, drop back to root table */ - if (drop != 0 && (huff & mask) != low) { - drop = 0; - len = root; - next = *table; - here.bits = (unsigned char)len; - } - - /* put invalid code marker in table */ - next[huff >> drop] = here; - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; } /* set return parameters */ diff --git a/lib/libvgz/trees.c b/lib/libvgz/trees.c index b494020..708649c 100644 --- a/lib/libvgz/trees.c +++ b/lib/libvgz/trees.c @@ -1,5 +1,5 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2010 Jean-loup Gailly + * Copyright (C) 1995-2012 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -74,11 +74,6 @@ local const uch bl_order[BL_CODES] * probability, to avoid transmitting the lengths for unused bit length codes. */ -#define Buf_size (8 * 2*sizeof(char)) -/* Number of bits used within bi_buf. (bi_buf might be implemented on - * more than 16 bits on some systems.) - */ - /* =========================================================================== * Local data. These are initialized only once. */ @@ -151,8 +146,8 @@ local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); local int build_bl_tree OF((deflate_state *s)); local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, int blcodes)); -local void compress_block OF((deflate_state *s, ct_data *ltree, - ct_data *dtree)); +local void compress_block OF((deflate_state *s, const ct_data *ltree, + const ct_data *dtree)); local int detect_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); local void bi_windup OF((deflate_state *s)); @@ -399,7 +394,6 @@ void ZLIB_INTERNAL _tr_init(s) s->bi_buf = 0; s->bi_valid = 0; - s->last_eob_len = 8; /* enough lookahead for inflate */ #ifdef DEBUG s->compressed_len = 0L; s->bits_sent = 0L; @@ -883,15 +877,17 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) } /* =========================================================================== + * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) + */ +void ZLIB_INTERNAL _tr_flush_bits(s) + deflate_state *s; +{ + bi_flush(s); +} + +/* =========================================================================== * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. - * The current inflate code requires 9 bits of lookahead. If the - * last two codes for the previous block (real code plus EOB) were coded - * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode - * the last real code. In this case we send two empty static blocks instead - * of one. (There are no problems if the previous block is stored or fixed.) - * To simplify the code, we assume the worst case of last real code encoded - * on one bit only. */ void ZLIB_INTERNAL _tr_align(s) deflate_state *s; @@ -902,20 +898,6 @@ void ZLIB_INTERNAL _tr_align(s) s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); - /* Of the 10 bits for the empty block, we have already sent - * (10 - bi_valid) bits. The lookahead for the last real code (before - * the EOB of the previous block) was thus at least one plus the length - * of the EOB plus what we have just sent of the empty static block. - */ - if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; -#endif - bi_flush(s); - } - s->last_eob_len = 7; } /* =========================================================================== @@ -933,7 +915,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) if (last) s->strm->last_bit = - (s->strm->total_out + s->pending) * 8 + s->bi_valid; + (s->strm->total_out + s->pending) * 8 + s->bi_valid; /* Build the Huffman trees unless a stored block is forced */ if (s->level > 0) { @@ -994,8 +976,8 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { #endif send_bits(s, (STATIC_TREES<<1)+last, 3); - compress_block(s, (ct_data *)(uintptr_t)static_ltree, - (ct_data *)(uintptr_t)static_dtree); + compress_block(s, (const ct_data *)static_ltree, + (const ct_data *)static_dtree); #ifdef DEBUG s->compressed_len += 3 + s->static_len; #endif @@ -1003,7 +985,8 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) send_bits(s, (DYN_TREES<<1)+last, 3); send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); - compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); + compress_block(s, (const ct_data *)s->dyn_ltree, + (const ct_data *)s->dyn_dtree); #ifdef DEBUG s->compressed_len += 3 + s->opt_len; #endif @@ -1016,8 +999,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) if (last) { s->strm->stop_bit = - (s->strm->total_out + s->pending) * 8 + s->bi_valid; - + (s->strm->total_out + s->pending) * 8 + s->bi_valid; bi_windup(s); #ifdef DEBUG s->compressed_len += 7; /* align on byte boundary */ @@ -1083,8 +1065,8 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc) */ local void compress_block(s, ltree, dtree) deflate_state *s; - ct_data *ltree; /* literal tree */ - ct_data *dtree; /* distance tree */ + const ct_data *ltree; /* literal tree */ + const ct_data *dtree; /* distance tree */ { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ @@ -1126,7 +1108,6 @@ local void compress_block(s, ltree, dtree) } while (lx < s->last_lit); send_code(s, END_BLOCK, ltree); - s->last_eob_len = ltree[END_BLOCK].Len; } /* =========================================================================== @@ -1234,7 +1215,6 @@ local void copy_block(s, buf, len, header) int header; /* true if block header must be written */ { bi_windup(s); /* align on byte boundary */ - s->last_eob_len = 8; /* enough lookahead for inflate */ if (header) { put_short(s, (ush)len); diff --git a/lib/libvgz/uncompr.c b/lib/libvgz/uncompr.c index 78324b1..0f6a951 100644 --- a/lib/libvgz/uncompr.c +++ b/lib/libvgz/uncompr.c @@ -30,7 +30,7 @@ int ZEXPORT uncompress (dest, destLen, source, sourceLen) z_stream stream; int err; - stream.next_in = (Bytef*)(uintptr_t)source; + stream.next_in = (z_const Bytef *)source; stream.avail_in = (uInt)sourceLen; /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; diff --git a/lib/libvgz/vgz.h b/lib/libvgz/vgz.h index f082e41..6846fa0 100644 --- a/lib/libvgz/vgz.h +++ b/lib/libvgz/vgz.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.5, April 19th, 2010 + version 1.2.8, April 28th, 2013 - Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -24,8 +24,8 @@ The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef ZLIB_H @@ -37,11 +37,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.5" -#define ZLIB_VERNUM 0x1250 +#define ZLIB_VERSION "1.2.8" +#define ZLIB_VERNUM 0x1280 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_REVISION 8 #define ZLIB_VER_SUBREVISION 0 /* @@ -83,15 +83,15 @@ typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ + z_const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ + uLong total_in; /* total number of input bytes read so far */ Bytef *next_out; /* next output byte should be put there */ uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ + uLong total_out; /* total number of bytes output so far */ - const char *msg; /* last error message, NULL if no error */ + z_const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ @@ -331,8 +331,9 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); Z_FINISH can be used immediately after deflateInit if all the compression is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. + value returned by deflateBound (see below). Then deflate is guaranteed to + return Z_STREAM_END. If not enough output space is provided, deflate will + not return Z_STREAM_END, and it must be called again as described above. deflate() sets strm->adler to the adler32 checksum of all input read so far (that is, total_in bytes). @@ -455,23 +456,29 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all the uncompressed data. (The size - of the uncompressed data may have been saved by the compressor for this - purpose.) The next operation on this stream must be inflateEnd to deallocate - the decompression state. The use of Z_FINISH is never required, but can be - used to inform inflate that a faster approach may be used for the single - inflate() call. + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. In this implementation, inflate() always flushes as much output as possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK or Z_TREES is used. + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, + strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed adler32 checksum is equal to that saved by the compressor and returns Z_STREAM_END @@ -482,7 +489,9 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); initializing with inflateInit2(). Any information contained in the gzip header is not retained, so applications that need that information should instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. + perform their own processing of the gzip header and trailer. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + producted so far. The CRC-32 is checked against the gzip trailer. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has @@ -584,10 +593,15 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, uInt dictLength)); /* Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any call - of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly @@ -614,8 +628,8 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, @@ -692,8 +706,28 @@ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). -*/ + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, int bits, @@ -707,8 +741,9 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, than or equal to 16, and that many of the least significant bits of value will be inserted in the output. - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, @@ -794,10 +829,11 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the adler32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is @@ -807,19 +843,38 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, inflate(). */ +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); /* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been - found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the - success case, the application may save the current current value of total_in - which indicates where valid compressed data was found. In the error case, - the application may repeatedly call inflateSync, providing more input each - time, until success or end of the input data. + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. */ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, @@ -966,12 +1021,13 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + the parameters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, @@ -979,11 +1035,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, out_func out, void FAR *out_desc)); /* inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. @@ -1092,6 +1149,7 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); 27-31: 0 (reserved) */ +#ifndef Z_SOLO /* utility functions */ @@ -1153,10 +1211,11 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. */ - /* gzip file access functions */ /* @@ -1166,7 +1225,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, wrapper, documented in RFC 1952, wrapped around a deflate stream. */ -typedef voidp gzFile; /* opaque gzip file descriptor */ +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); @@ -1176,13 +1235,28 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) Also "a" - can be used instead of "w" to request that the gzip stream that will be - written be appended to the file. "+" will result in an error, since reading - and writing to the same gzip file is not supported. + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. gzopen returns NULL if the file could not be opened, if there was insufficient memory to allocate the gzFile state, or if an invalid mode was @@ -1201,7 +1275,11 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. gzdopen returns NULL if there was insufficient memory to allocate the gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not @@ -1239,14 +1317,26 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); /* Reads the given number of uncompressed bytes from the compressed file. If - the input file was not in gzip format, gzread copies the given number of - bytes into the buffer. + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream, or failing that, reading the rest - of the input file directly without decompression. The entire input file - will be read if gzread is called until it returns less than the requested - len. + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. gzread returns the number of uncompressed bytes actually read, less than len for end of file, or -1 for error. @@ -1260,7 +1350,7 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, error. */ -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); /* Converts, formats, and writes the arguments to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of @@ -1305,7 +1395,10 @@ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); /* Reads one byte from the compressed file. gzgetc returns this byte or -1 - in case of end of file or error. + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. */ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); @@ -1401,9 +1494,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); /* Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. This state can change from - false to true while reading the input file if the end of a gzip stream is - reached, but is followed by data that is not another gzip stream. + (0) if file is a gzip stream being decompressed. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. @@ -1412,6 +1503,13 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); cause buffers to be allocated to allow reading the file to determine if it is a gzip file. Therefore if gzbuffer() is used, it should be called before gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) */ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); @@ -1423,7 +1521,8 @@ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, or Z_OK on success. + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. */ ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); @@ -1461,6 +1560,7 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); file that is being written concurrently. */ +#endif /* !Z_SOLO */ /* checksum functions */ @@ -1496,16 +1596,17 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. */ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. If buf is Z_NULL, this function returns the required - initial value for the for the crc. Pre- and post-conditioning (one's - complement) is performed within this function so it shouldn't be done by the - application. + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. Usage example: @@ -1548,17 +1649,42 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); #define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) #define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) #define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) #define inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) + ZLIB_VERSION, (int)sizeof(z_stream)) + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +#endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if @@ -1566,7 +1692,7 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, * functions are changed to 64 bits) -- in case these are set on systems * without large file support, _LFS64_LARGEFILE must also be true */ -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +#ifdef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); @@ -1575,14 +1701,23 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); #endif -#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# ifdef _LARGEFILE64_SOURCExxx +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); @@ -1599,6 +1734,13 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); #endif +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + /* hack for buggy compilers */ #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) struct internal_state {int dummy;}; @@ -1607,8 +1749,21 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, /* undocumented functions */ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif #ifdef __cplusplus } diff --git a/lib/libvgz/zconf.h b/lib/libvgz/zconf.h index 9fb2c9a..63eda6a 100644 --- a/lib/libvgz/zconf.h +++ b/lib/libvgz/zconf.h @@ -1,15 +1,13 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2010 Jean-loup Gailly. + * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ -/* @(#) $Id$ */ +/* @(#) $FreeBSD: head/lib/libz/zconf.h 250261 2013-05-05 06:20:49Z delphij $ */ #ifndef ZCONF_H #define ZCONF_H -#include - /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. @@ -17,11 +15,13 @@ * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET /* all linked symbols */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits # define _tr_flush_block z__tr_flush_block # define _tr_init z__tr_init # define _tr_stored_block z__tr_stored_block @@ -29,9 +29,11 @@ # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 @@ -42,44 +44,53 @@ # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams +# define deflatePending z_deflatePending # define deflatePrime z_deflatePrime # define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep # define deflateSetDictionary z_deflateSetDictionary # define deflateSetHeader z_deflateSetHeader # define deflateTune z_deflateTune # define deflate_copyright z_deflate_copyright # define get_crc_table z_get_crc_table -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzvprintf z_gzvprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd @@ -94,16 +105,22 @@ # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 # define inflateSetDictionary z_inflateSetDictionary +# define inflateGetDictionary z_inflateGetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine +# define inflateResetKeep z_inflateResetKeep # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table -# define uncompress z_uncompress +# ifndef Z_SOLO +# define uncompress z_uncompress +# endif # define zError z_zError -# define zcalloc z_zcalloc -# define zcfree z_zcfree +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion @@ -113,7 +130,9 @@ # define alloc_func z_alloc_func # define charf z_charf # define free_func z_free_func -# define gzFile z_gzFile +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif # define gz_header z_gz_header # define gz_headerp z_gz_headerp # define in_func z_in_func @@ -199,6 +218,12 @@ # endif #endif +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) # define NO_DUMMY_DECL @@ -245,6 +270,14 @@ # endif #endif +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have @@ -358,12 +391,47 @@ typedef uLong FAR uLongf; typedef Byte *voidp; #endif -#if 1 /* was set to #if 1 by ./configure */ +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#if 0 /* was set to #if 0 by ./configure */ # define Z_HAVE_UNISTD_H #endif +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + #ifdef STDC -# include /* for off_t */ +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and @@ -372,42 +440,63 @@ typedef uLong FAR uLongf; * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ -#if -_LARGEFILE64_SOURCE - -1 == 1 +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif -#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif # endif #endif -#ifndef SEEK_SET +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif +/* + * This is hard-configured for FreeBSD. + */ +#define z_off_t off_t +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + #ifndef z_off_t # define z_off_t long #endif -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +#if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else -# define z_off64_t z_off_t -#endif - -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif #endif /* MVS linker does not support external names larger than 8 bytes */ diff --git a/lib/libvgz/zutil.c b/lib/libvgz/zutil.c index 898ed34..23d2ebe 100644 --- a/lib/libvgz/zutil.c +++ b/lib/libvgz/zutil.c @@ -1,17 +1,20 @@ /* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2005, 2010 Jean-loup Gailly. + * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" +#ifndef Z_SOLO +# include "gzguts.h" +#endif #ifndef NO_DUMMY_DECL struct internal_state {int dummy;}; /* for buggy compilers */ #endif -const char * const z_errmsg[10] = { +z_const char * const z_errmsg[10] = { "need dictionary", /* Z_NEED_DICT 2 */ "stream end", /* Z_STREAM_END 1 */ "", /* Z_OK 0 */ @@ -85,27 +88,27 @@ uLong ZEXPORT zlibCompileFlags() #ifdef FASTEST flags += 1L << 21; #endif -#ifdef STDC +#if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifdef NO_vsnprintf - flags += 1L << 25; + flags += 1L << 25; # ifdef HAS_vsprintf_void - flags += 1L << 26; + flags += 1L << 26; # endif # else # ifdef HAS_vsnprintf_void - flags += 1L << 26; + flags += 1L << 26; # endif # endif #else - flags += 1L << 24; + flags += 1L << 24; # ifdef NO_snprintf - flags += 1L << 25; + flags += 1L << 25; # ifdef HAS_sprintf_void - flags += 1L << 26; + flags += 1L << 26; # endif # else # ifdef HAS_snprintf_void - flags += 1L << 26; + flags += 1L << 26; # endif # endif #endif @@ -181,6 +184,7 @@ void ZLIB_INTERNAL zmemzero(dest, len) } #endif +#ifndef Z_SOLO #ifdef SYS16BIT @@ -316,3 +320,5 @@ void ZLIB_INTERNAL zcfree (opaque, ptr) } #endif /* MY_ZCALLOC */ + +#endif /* !Z_SOLO */ diff --git a/lib/libvgz/zutil.h b/lib/libvgz/zutil.h index 0c7456e..f6dd6d5 100644 --- a/lib/libvgz/zutil.h +++ b/lib/libvgz/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2010 Jean-loup Gailly. + * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -13,7 +13,7 @@ #ifndef ZUTIL_H #define ZUTIL_H -#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +#ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL @@ -21,7 +21,7 @@ #include "vgz.h" -#ifdef STDC +#if defined(STDC) && !defined(Z_SOLO) # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) # include # endif @@ -29,6 +29,10 @@ # include #endif +#ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ +#endif + #ifndef local # define local static #endif @@ -40,7 +44,7 @@ typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; -extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] @@ -78,16 +82,18 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) # define OS_CODE 0x00 -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include # endif -# else /* MSC or DJGPP */ -# include # endif #endif @@ -107,18 +113,20 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #ifdef OS2 # define OS_CODE 0x06 -# ifdef M_I86 +# if defined(M_I86) && !defined(Z_SOLO) # include # endif #endif #if defined(MACOS) || defined(TARGET_OS_MAC) # define OS_CODE 0x07 -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif # endif # endif #endif @@ -153,14 +161,15 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # endif #endif -#if defined(__BORLANDC__) +#if defined(__BORLANDC__) && !defined(MSDOS) #pragma warn -8004 #pragma warn -8008 #pragma warn -8066 #endif /* provide prototypes for these when building zlib without LFS */ -#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); #endif @@ -177,42 +186,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* functions */ -#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif -#if defined(__CYGWIN__) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif -#ifndef HAVE_VSNPRINTF -# ifdef MSDOS - /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ -# define NO_vsnprintf -# endif -# ifdef __TURBOC__ -# define NO_vsnprintf -# endif -# ifdef WIN32 - /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) -# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) -# define vsnprintf _vsnprintf -# endif -# endif -# endif -# ifdef __SASC -# define NO_vsnprintf -# endif -#endif -#ifdef VMS -# define NO_vsnprintf -#endif - -#if defined(pyr) +#if defined(pyr) || defined(Z_SOLO) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) @@ -261,14 +235,19 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # define Tracecv(c,x) #endif - -voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, - unsigned size)); -void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + #endif /* ZUTIL_H */ From phk at varnish-cache.org Mon Sep 9 09:20:42 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 09 Sep 2013 11:20:42 +0200 Subject: [master] 4e5ee71 Rename vcl_lookup{} back to vcl_hit{}. Message-ID: commit 4e5ee71f7b3e75edb6abe4d9fc9a05d301bad818 Author: Poul-Henning Kamp Date: Mon Sep 9 09:19:57 2013 +0000 Rename vcl_lookup{} back to vcl_hit{}. The only real trouble was purges, and they now have their own vcl_purge{} Sorry for the detour... diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 9e0d35a..d5b8722 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -80,11 +80,11 @@ DOT acceptor -> recv [style=bold,color=green] * DOT deliver [ DOT shape=record -DOT label="{cnt_deliver:|Filter obj.-\>resp.|{vcl_deliver\{\}|{req.|resp.}}|{deliver(stream)?|restart?|deliver?}}" +DOT label="{cnt_deliver:|Filter obj.-\>resp.|{vcl_deliver\{\}|{req.|resp.}}|{restart?|deliver?}}" DOT ] DOT deliver:deliver:s -> DONE [style=bold,color=green] -DOT deliver:stream:s -> stream [style=bold,color=red] -DOT deliver:stream:s -> stream [style=bold,color=blue] +DOT deliver:deliver:s -> DONE [style=bold,color=red] +DOT deliver:deliver:s -> DONE [style=bold,color=blue] * */ @@ -323,7 +323,7 @@ DOT label="{cnt_lookup:|hash lookup|{busy?|exp?|exp+busy?| DOT ] DOT lookup2 [ DOT shape=record -DOT label="{cnt_lookup:|{vcl_lookup\{\}|req.*, obj.*}|{deliver?|error?|restart?|fetch?|pass?}}" +DOT label="{cnt_lookup:|{vcl_hit\{\}|req.*, obj.*}|{deliver?|error?|restart?|fetch?|pass?}}" DOT ] DOT } DOT lookup:busy:w -> lookup:top:w [label="(waitinglist)"] @@ -411,7 +411,7 @@ cnt_lookup(struct worker *wrk, struct req *req) VSLb(req->vsl, SLT_Hit, "%u", req->obj->vxid); - VCL_lookup_method(req->vcl, wrk, req, NULL, req->http->ws); + VCL_hit_method(req->vcl, wrk, req, NULL, req->http->ws); switch (wrk->handling) { case VCL_RET_DELIVER: diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c index 36b2a43..e4aecb1 100644 --- a/bin/varnishd/cache/cache_vrt.c +++ b/bin/varnishd/cache/cache_vrt.c @@ -496,7 +496,7 @@ VRT_purge(const struct vrt_ctx *ctx, double ttl, double grace) CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); CHECK_OBJ_NOTNULL(ctx->req->wrk, WORKER_MAGIC); - if (ctx->method == VCL_MET_LOOKUP) + if (ctx->method == VCL_MET_HIT) HSH_Purge(ctx->req->wrk, ctx->req->obj->objcore->objhead, ttl, grace); else if (ctx->method == VCL_MET_MISS) diff --git a/bin/varnishd/default.vcl b/bin/varnishd/default.vcl index 569cea2..46d3a21 100644 --- a/bin/varnishd/default.vcl +++ b/bin/varnishd/default.vcl @@ -97,7 +97,7 @@ sub vcl_purge { return (error(200, "Purged")); } -sub vcl_lookup { +sub vcl_hit { if (obj.ttl >= 0s) { // A pure unadultered hit, deliver it return (deliver); diff --git a/bin/varnishtest/tests/b00019.vtc b/bin/varnishtest/tests/b00019.vtc index 91c0e68..5566723 100644 --- a/bin/varnishtest/tests/b00019.vtc +++ b/bin/varnishtest/tests/b00019.vtc @@ -21,7 +21,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_lookup { + sub vcl_hit { return (restart); } diff --git a/bin/varnishtest/tests/c00010.vtc b/bin/varnishtest/tests/c00010.vtc index e9c78a9..238dada 100644 --- a/bin/varnishtest/tests/c00010.vtc +++ b/bin/varnishtest/tests/c00010.vtc @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_lookup { + sub vcl_hit { return(pass); } } -start diff --git a/bin/varnishtest/tests/c00041.vtc b/bin/varnishtest/tests/c00041.vtc index e9dd2cd..c51cf53 100644 --- a/bin/varnishtest/tests/c00041.vtc +++ b/bin/varnishtest/tests/c00041.vtc @@ -40,7 +40,7 @@ server s1 { varnish v1 -vcl+backend { sub vcl_miss { if (req.http.purge == "yes") { purge; } } - sub vcl_lookup { if (req.http.purge == "yes") { purge; return(restart);} } + sub vcl_hit { if (req.http.purge == "yes") { purge; return(restart);} } } -start client c1 { diff --git a/bin/varnishtest/tests/p00001.vtc b/bin/varnishtest/tests/p00001.vtc index adfc1f0..ac95149 100644 --- a/bin/varnishtest/tests/p00001.vtc +++ b/bin/varnishtest/tests/p00001.vtc @@ -24,7 +24,7 @@ client c1 { varnish v1 -stop varnish v1 -vcl+backend { - sub vcl_lookup { + sub vcl_hit { set obj.ttl = 1 s; } } diff --git a/bin/varnishtest/tests/r00310.vtc b/bin/varnishtest/tests/r00310.vtc index 8097a6b..6a5ce22 100644 --- a/bin/varnishtest/tests/r00310.vtc +++ b/bin/varnishtest/tests/r00310.vtc @@ -1,9 +1,9 @@ -varnishtest "Test obj.http.x-cache in vcl_lookup" +varnishtest "Test obj.http.x-cache in vcl_hit" -varnish v1 -errvcl {'obj.http.x-cache': cannot be set in method 'vcl_lookup'.} { +varnish v1 -errvcl {'obj.http.x-cache': cannot be set in method 'vcl_hit'.} { backend foo { .host = "localhost"; } - sub vcl_lookup { + sub vcl_hit { set obj.http.x-cache = "hit"; } } diff --git a/bin/varnishtest/tests/r00365.vtc b/bin/varnishtest/tests/r00365.vtc index a703a66..dc1d590 100644 --- a/bin/varnishtest/tests/r00365.vtc +++ b/bin/varnishtest/tests/r00365.vtc @@ -1,4 +1,4 @@ -varnishtest "Test restarts in vcl_lookup" +varnishtest "Test restarts in vcl_hit" server s1 { rxreq @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_lookup { + sub vcl_hit { set obj.ttl = 0s; return (restart); } diff --git a/bin/varnishtest/tests/r00411.vtc b/bin/varnishtest/tests/r00411.vtc index 3d1e832..98c478e 100644 --- a/bin/varnishtest/tests/r00411.vtc +++ b/bin/varnishtest/tests/r00411.vtc @@ -11,7 +11,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_lookup { + sub vcl_hit { if (obj.http.X-Magic-Redirect == "1") { set req.url = obj.http.Location; return (restart); diff --git a/bin/varnishtest/tests/r00444.vtc b/bin/varnishtest/tests/r00444.vtc index 2448b93..899ab57 100644 --- a/bin/varnishtest/tests/r00444.vtc +++ b/bin/varnishtest/tests/r00444.vtc @@ -25,7 +25,7 @@ varnish v1 -vcl+backend { return (hash); } } - sub vcl_lookup { + sub vcl_hit { if (req.method == "POST") { /* Get rid of this object */ set obj.ttl = 0s; diff --git a/bin/varnishtest/tests/r00956.vtc b/bin/varnishtest/tests/r00956.vtc index c8196d1..2744a44 100644 --- a/bin/varnishtest/tests/r00956.vtc +++ b/bin/varnishtest/tests/r00956.vtc @@ -11,7 +11,7 @@ varnish v1 -vcl+backend { set beresp.http.fooB = beresp.ttl; set beresp.http.barB = "xxx"; } - sub vcl_lookup { + sub vcl_hit { set req.http.foo = obj.ttl; set obj.ttl = 7s; set obj.grace = 120s; diff --git a/bin/varnishtest/tests/r01113.vtc b/bin/varnishtest/tests/r01113.vtc index debeb90..75fa317 100644 --- a/bin/varnishtest/tests/r01113.vtc +++ b/bin/varnishtest/tests/r01113.vtc @@ -15,7 +15,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_lookup { + sub vcl_hit { if (req.url == "/hit") { return(restart); } diff --git a/bin/varnishtest/tests/v00018.vtc b/bin/varnishtest/tests/v00018.vtc index 6b6fa1f..748e92f 100644 --- a/bin/varnishtest/tests/v00018.vtc +++ b/bin/varnishtest/tests/v00018.vtc @@ -2,14 +2,14 @@ varnishtest "VCL compiler coverage test: vcc_action.c" varnish v1 -vcl { backend b { .host = "127.0.0.1"; } - sub vcl_lookup { return (restart) ; } + sub vcl_hit { return (restart) ; } sub vcl_miss { rollback; return (restart); } } varnish v1 -vcl { backend b { .host = "127.0.0.1"; } sub vcl_miss { return(error(100,req.url)); } - sub vcl_lookup { return(error(100,"the butter please")); } + sub vcl_hit { return(error(100,"the butter please")); } } varnish v1 -errvcl {Variable 'server.port' is read only.} { diff --git a/bin/varnishtest/tests/v00023.vtc b/bin/varnishtest/tests/v00023.vtc index 10f9bb3..ca36194 100644 --- a/bin/varnishtest/tests/v00023.vtc +++ b/bin/varnishtest/tests/v00023.vtc @@ -10,7 +10,7 @@ server s1 { } -start varnish v1 -vcl+backend { - sub vcl_lookup { + sub vcl_hit { set obj.ttl = 0s; return (restart); } diff --git a/bin/varnishtest/tests/v00025.vtc b/bin/varnishtest/tests/v00025.vtc index 26f3384..a191969 100644 --- a/bin/varnishtest/tests/v00025.vtc +++ b/bin/varnishtest/tests/v00025.vtc @@ -25,7 +25,7 @@ sub vcl_backend_response { } } -sub vcl_lookup { +sub vcl_hit { if (obj.grace < 3m) { set obj.grace = 1m; } else { diff --git a/lib/libvcl/generate.py b/lib/libvcl/generate.py index 0125d73..979f2b1 100755 --- a/lib/libvcl/generate.py +++ b/lib/libvcl/generate.py @@ -84,7 +84,7 @@ returns =( ('hash', "C", ('lookup',)), ('purge', "C", ('error', 'fetch',)), ('miss', "C", ('error', 'restart', 'pass', 'fetch',)), - ('lookup', "C", ('error', 'restart', 'pass', 'fetch', 'deliver',)), + ('hit', "C", ('error', 'restart', 'pass', 'fetch', 'deliver',)), ('backend_fetch', "B", ('fetch', 'abandon')), ('backend_response', "B", ('deliver', 'retry', 'abandon')), ('deliver', "C", ('restart', 'deliver',)), @@ -359,8 +359,8 @@ sp_variables = [ ), ('obj.proto', 'STRING', - ( 'lookup', 'error',), - ( 'lookup', 'error',), + ( 'hit', 'error',), + ( 'hit', 'error',), ), ('obj.status', 'INT', @@ -374,37 +374,37 @@ sp_variables = [ ), ('obj.hits', 'INT', - ( 'lookup', 'deliver',), + ( 'hit', 'deliver',), ( ), ), ('obj.http.', 'HEADER', - ( 'lookup', 'error',), + ( 'hit', 'error',), ( 'error',), # XXX ? ), ('obj.ttl', 'DURATION', - ( 'lookup', 'error',), - ( 'lookup', 'error',), + ( 'hit', 'error',), + ( 'hit', 'error',), ), ('obj.grace', 'DURATION', - ( 'lookup', 'error',), - ( 'lookup', 'error',), + ( 'hit', 'error',), + ( 'hit', 'error',), ), ('obj.keep', 'DURATION', - ( 'lookup', 'error',), - ( 'lookup', 'error',), + ( 'hit', 'error',), + ( 'hit', 'error',), ), ('obj.lastuse', 'DURATION', - ( 'lookup', 'deliver', 'error',), + ( 'hit', 'deliver', 'error',), ( ), ), ('obj.uncacheable', 'BOOL', - ( 'lookup', 'deliver', 'error',), + ( 'hit', 'deliver', 'error',), ( ), ), ('resp.proto', diff --git a/lib/libvcl/vcc_action.c b/lib/libvcl/vcc_action.c index 6b08b34..1b31fb7 100644 --- a/lib/libvcl/vcc_action.c +++ b/lib/libvcl/vcc_action.c @@ -408,7 +408,7 @@ static struct action_table { { "error", parse_error }, { "hash_data", parse_hash_data, VCL_MET_HASH }, { "new", parse_new, VCL_MET_INIT}, - { "purge", parse_purge, VCL_MET_MISS | VCL_MET_LOOKUP }, + { "purge", parse_purge, VCL_MET_MISS | VCL_MET_HIT }, { "remove", parse_unset }, /* backward compatibility */ { "return", parse_return }, { "rollback", parse_rollback }, From phk at varnish-cache.org Mon Sep 9 12:18:32 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 09 Sep 2013 14:18:32 +0200 Subject: [master] 8f06d0f If vcl_hit{} returns fetch{} without a BUSY object, treat is as a pass, it will be anyway. Message-ID: commit 8f06d0f81741bd680eebdd0cc923206b642c0204 Author: Poul-Henning Kamp Date: Mon Sep 9 12:17:55 2013 +0000 If vcl_hit{} returns fetch{} without a BUSY object, treat is as a pass, it will be anyway. Fixes #1335 diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index d5b8722..34b8138 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -426,7 +426,18 @@ cnt_lookup(struct worker *wrk, struct req *req) case VCL_RET_FETCH: (void)HSH_DerefObj(&wrk->stats, &req->obj); req->objcore = boc; - req->req_step = R_STP_MISS; + if (req->objcore != NULL) + req->req_step = R_STP_MISS; + else { + /* + * We don't have a busy object, so treat this + * lige a pass + */ + VSLb(req->vsl, SLT_VCL_Error, + "vcl_hit{} returns fetch without busy object." + " Doing pass."); + req->req_step = R_STP_PASS; + } return (REQ_FSM_MORE); case VCL_RET_RESTART: req->req_step = R_STP_RESTART; diff --git a/bin/varnishtest/tests/r01335.vtc b/bin/varnishtest/tests/r01335.vtc new file mode 100644 index 0000000..8a34d5b --- /dev/null +++ b/bin/varnishtest/tests/r01335.vtc @@ -0,0 +1,25 @@ +varnishtest "#1335 fetch without busy object" + +server s1 { + rxreq + txresp -bodylen 5 + rxreq + txresp -bodylen 6 +} -start + +varnish v1 -vcl+backend { + sub vcl_hit { + if (req.http.two == "2") { + return (fetch); + } + } +} -start + +client c1 { + txreq + rxresp +} -run +client c1 { + txreq -hdr "two: 2" + rxresp +} -run From daghf at varnish-cache.org Mon Sep 9 15:14:36 2013 From: daghf at varnish-cache.org (Dag Haavi Finstad) Date: Mon, 09 Sep 2013 17:14:36 +0200 Subject: [master] bab1223 Add gzguts.h to dist Message-ID: commit bab122309861f91edb7a5d7e5a9d09299ccafb2c Author: Dag Haavi Finstad Date: Mon Sep 9 17:15:27 2013 +0200 Add gzguts.h to dist diff --git a/lib/libvgz/Makefile.am b/lib/libvgz/Makefile.am index 54226bb..d9c0dae 100644 --- a/lib/libvgz/Makefile.am +++ b/lib/libvgz/Makefile.am @@ -13,6 +13,7 @@ libvgz_la_SOURCES = \ crc32.h \ deflate.c \ deflate.h \ + gzguts.h \ infback.c \ inffast.c \ inffast.h \ From phk at varnish-cache.org Tue Sep 10 07:25:47 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 10 Sep 2013 09:25:47 +0200 Subject: [master] 8c4658a Add support for directors reporting time of last health-change Message-ID: commit 8c4658af548dfb056c81085aa8f4873323968b32 Author: Poul-Henning Kamp Date: Tue Sep 10 07:25:30 2013 +0000 Add support for directors reporting time of last health-change diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c index 092f43f..3c3e460 100644 --- a/bin/varnishd/cache/cache_backend.c +++ b/bin/varnishd/cache/cache_backend.c @@ -230,15 +230,14 @@ vbe_NewConn(void) * items would never time out once the threshold is reached. */ -static unsigned int -vbe_Healthy(const struct vdi_simple *vs) +unsigned +VBE_Healthy(const struct backend *backend, double *changed) { - struct backend *backend; - - CHECK_OBJ_NOTNULL(vs, VDI_SIMPLE_MAGIC); - backend = vs->backend; CHECK_OBJ_NOTNULL(backend, BACKEND_MAGIC); + if (changed != NULL) + *changed = backend->health_changed; + if (backend->admin_health == ah_probe && !backend->healthy) return (0); @@ -301,7 +300,7 @@ vbe_GetVbe(struct busyobj *bo, struct vdi_simple *vs) VBE_ReleaseConn(vc); } - if (!vbe_Healthy(vs)) { + if (!VBE_Healthy(bp, NULL)) { VSC_C_main->backend_unhealthy++; return (NULL); } @@ -391,13 +390,16 @@ vdi_simple_getfd(const struct director *d, struct busyobj *bo) } static unsigned -vdi_simple_healthy(const struct director *d) +vdi_simple_healthy(const struct director *d, double *changed) { struct vdi_simple *vs; + struct backend *be; CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); CAST_OBJ_NOTNULL(vs, d->priv, VDI_SIMPLE_MAGIC); - return (vbe_Healthy(vs)); + be = vs->backend; + CHECK_OBJ_NOTNULL(be, BACKEND_MAGIC); + return (VBE_Healthy(be, changed)); } static void diff --git a/bin/varnishd/cache/cache_backend.h b/bin/varnishd/cache/cache_backend.h index d186ecc..f3931e9 100644 --- a/bin/varnishd/cache/cache_backend.h +++ b/bin/varnishd/cache/cache_backend.h @@ -77,7 +77,7 @@ struct vrt_backend_probe; typedef struct vbc *vdi_getfd_f(const struct director *, struct busyobj *); typedef void vdi_fini_f(const struct director *); -typedef unsigned vdi_healthy(const struct director *); +typedef unsigned vdi_healthy(const struct director *, double *changed); struct director { unsigned magic; @@ -124,6 +124,7 @@ struct backend { struct vbp_target *probe; unsigned healthy; enum admin_health admin_health; + double health_changed; struct VSC_C_vbe *vsc; }; @@ -156,6 +157,7 @@ void VBE_ReleaseConn(struct vbc *vc); void VBE_DropRefConn(struct backend *); void VBE_DropRefVcl(struct backend *); void VBE_DropRefLocked(struct backend *b); +unsigned VBE_Healthy(const struct backend *b, double *changed); /* cache_backend_poll.c */ void VBP_Insert(struct backend *b, struct vrt_backend_probe const *p, diff --git a/bin/varnishd/cache/cache_backend_cfg.c b/bin/varnishd/cache/cache_backend_cfg.c index 24ed727..2d55147 100644 --- a/bin/varnishd/cache/cache_backend_cfg.c +++ b/bin/varnishd/cache/cache_backend_cfg.c @@ -43,6 +43,7 @@ #include "vcli_priv.h" #include "vsa.h" #include "vrt.h" +#include "vtim.h" /* * The list of backends is not locked, it is only ever accessed from @@ -230,6 +231,7 @@ VBE_AddBackend(struct cli *cli, const struct vrt_backend *vb) assert(b->ipv4 != NULL || b->ipv6 != NULL); b->healthy = 1; + b->health_changed = VTIM_real(); b->admin_health = ah_probe; VTAILQ_INSERT_TAIL(&backends, b, list); @@ -415,6 +417,8 @@ do_list(struct cli *cli, struct backend *b, void *priv) VBP_Summary(cli, b->probe); } + /* XXX: report b->health_changed */ + return (0); } @@ -435,11 +439,16 @@ static int __match_proto__() do_set_health(struct cli *cli, struct backend *b, void *priv) { enum admin_health state; + unsigned prev; (void)cli; state = *(enum admin_health*)priv; CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC); + prev = VBE_Healthy(b, NULL); b->admin_health = state; + if (prev != VBE_Healthy(b, NULL)) + b->health_changed = VTIM_real(); + return (0); } diff --git a/bin/varnishd/cache/cache_backend_poll.c b/bin/varnishd/cache/cache_backend_poll.c index f93fe2f..4cc03ce 100644 --- a/bin/varnishd/cache/cache_backend_poll.c +++ b/bin/varnishd/cache/cache_backend_poll.c @@ -280,13 +280,16 @@ vbp_has_poked(struct vbp_target *vt) if (vt->good >= vt->probe.threshold) { if (vt->backend->healthy) logmsg = "Still healthy"; - else + else { logmsg = "Back healthy"; + vt->backend->health_changed = VTIM_real(); + } vt->backend->healthy = 1; } else { - if (vt->backend->healthy) + if (vt->backend->healthy) { logmsg = "Went sick"; - else + vt->backend->health_changed = VTIM_real(); + } else logmsg = "Still sick"; vt->backend->healthy = 0; } diff --git a/bin/varnishd/cache/cache_dir.c b/bin/varnishd/cache/cache_dir.c index 5d7939a..ae6cb2d 100644 --- a/bin/varnishd/cache/cache_dir.c +++ b/bin/varnishd/cache/cache_dir.c @@ -116,10 +116,6 @@ VDI_GetFd(const struct director *d, struct busyobj *bo) } /* Check health ------------------------------------------------------ - * - * The target is really an objhead pointer, but since it can not be - * dereferenced during health-checks, we pass it as uintptr_t, which - * hopefully will make people investigate, before mucking about with it. */ int @@ -127,5 +123,5 @@ VDI_Healthy(const struct director *d) { CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); - return (d->healthy(d)); + return (d->healthy(d, NULL)); } diff --git a/lib/libvmod_directors/fall_back.c b/lib/libvmod_directors/fall_back.c index 4c86b7e..edec2af 100644 --- a/lib/libvmod_directors/fall_back.c +++ b/lib/libvmod_directors/fall_back.c @@ -45,12 +45,12 @@ struct vmod_directors_fallback { }; static unsigned __match_proto__(vdi_healthy) -vmod_rr_healthy(const struct director *dir) +vmod_rr_healthy(const struct director *dir, double *changed) { struct vmod_directors_fallback *rr; CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_FALLBACK_MAGIC); - return (vdir_any_healthy(rr->vd)); + return (vdir_any_healthy(rr->vd, changed)); } static struct vbc * __match_proto__(vdi_getfd_f) @@ -65,7 +65,7 @@ vmod_rr_getfd(const struct director *dir, struct busyobj *bo) for (u = 0; u < rr->vd->n_backend; u++) { be = rr->vd->backend[u]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); - if (be->healthy(be)) + if (be->healthy(be, NULL)) break; } vdir_unlock(rr->vd); diff --git a/lib/libvmod_directors/random.c b/lib/libvmod_directors/random.c index a31ec1b..22f0bb9 100644 --- a/lib/libvmod_directors/random.c +++ b/lib/libvmod_directors/random.c @@ -50,12 +50,12 @@ struct vmod_directors_random { }; static unsigned __match_proto__(vdi_healthy) -vmod_rr_healthy(const struct director *dir) +vmod_rr_healthy(const struct director *dir, double *changed) { struct vmod_directors_random *rr; CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_RANDOM_MAGIC); - return (vdir_any_healthy(rr->vd)); + return (vdir_any_healthy(rr->vd, changed)); } static struct vbc * __match_proto__(vdi_getfd_f) diff --git a/lib/libvmod_directors/round_robin.c b/lib/libvmod_directors/round_robin.c index f4b5eb6..629bbbf 100644 --- a/lib/libvmod_directors/round_robin.c +++ b/lib/libvmod_directors/round_robin.c @@ -46,12 +46,12 @@ struct vmod_directors_round_robin { }; static unsigned __match_proto__(vdi_healthy) -vmod_rr_healthy(const struct director *dir) +vmod_rr_healthy(const struct director *dir, double *changed) { struct vmod_directors_round_robin *rr; CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_ROUND_ROBIN_MAGIC); - return (vdir_any_healthy(rr->vd)); + return (vdir_any_healthy(rr->vd, changed)); } static struct vbc * __match_proto__(vdi_getfd_f) @@ -68,7 +68,7 @@ vmod_rr_getfd(const struct director *dir, struct busyobj *bo) be = rr->vd->backend[rr->nxt]; rr->nxt++; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); - if (be->healthy(be)) + if (be->healthy(be, NULL)) break; } vdir_unlock(rr->vd); diff --git a/lib/libvmod_directors/vdir.c b/lib/libvmod_directors/vdir.c index 8108a29..dacd648 100644 --- a/lib/libvmod_directors/vdir.c +++ b/lib/libvmod_directors/vdir.c @@ -128,21 +128,25 @@ vdir_add_backend(struct vdir *vd, VCL_BACKEND be, double weight) } unsigned -vdir_any_healthy(struct vdir *vd) +vdir_any_healthy(struct vdir *vd, double *changed) { unsigned retval = 0; VCL_BACKEND be; unsigned u; + double c; CHECK_OBJ_NOTNULL(vd, VDIR_MAGIC); vdir_lock(vd); + if (changed != NULL) + *changed = 0; for (u = 0; u < vd->n_backend; u++) { be = vd->backend[u]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); - if (be->healthy(be)) { - retval = 1; + retval = be->healthy(be, &c); + if (changed != NULL && c > *changed) + *changed = c; + if (retval) break; - } } vdir_unlock(vd); return (retval); @@ -185,7 +189,7 @@ vdir_pick_be(struct vdir *vd, double w, unsigned nloops) u = vdir_pick_by_weight(vd, w * tw, vbm); be = vd->backend[u]; CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC); - if (be->healthy(be)) + if (be->healthy(be, NULL)) break; if (l == 0) { vbm = vd->vbm; diff --git a/lib/libvmod_directors/vdir.h b/lib/libvmod_directors/vdir.h index 39ad9a1..d237b2d 100644 --- a/lib/libvmod_directors/vdir.h +++ b/lib/libvmod_directors/vdir.h @@ -47,5 +47,5 @@ void vdir_delete(struct vdir **vdp); void vdir_lock(struct vdir *vd); void vdir_unlock(struct vdir *vd); unsigned vdir_add_backend(struct vdir *vd, VCL_BACKEND be, double weight); -unsigned vdir_any_healthy(struct vdir *vd); +unsigned vdir_any_healthy(struct vdir *vd, double *changed); VCL_BACKEND vdir_pick_be(struct vdir *vd, double w, unsigned nloops); From phk at varnish-cache.org Tue Sep 10 07:44:41 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 10 Sep 2013 09:44:41 +0200 Subject: [master] 6327bfb Remove a unnecessary level of indirection when creating/destroying VCL created simple directors. Message-ID: commit 6327bfbfeb6284ade279808dd0160d9ea517d26b Author: Poul-Henning Kamp Date: Tue Sep 10 07:44:09 2013 +0000 Remove a unnecessary level of indirection when creating/destroying VCL created simple directors. diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c index 3c3e460..a7dfd2a 100644 --- a/bin/varnishd/cache/cache_backend.c +++ b/bin/varnishd/cache/cache_backend.c @@ -402,11 +402,14 @@ vdi_simple_healthy(const struct director *d, double *changed) return (VBE_Healthy(be, changed)); } -static void -vdi_simple_fini(const struct director *d) +/*--------------------------------------------------------------------*/ + +void +VRT_fini_dir(struct cli *cli, struct director *d) { struct vdi_simple *vs; + (void)cli; ASSERT_CLI(); CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); CAST_OBJ_NOTNULL(vs, d->priv, VDI_SIMPLE_MAGIC); @@ -415,11 +418,11 @@ vdi_simple_fini(const struct director *d) free(vs->dir.vcl_name); vs->dir.magic = 0; FREE_OBJ(vs); + d->priv = NULL; } void -VRT_init_dir_simple(struct cli *cli, struct director **bp, int idx, - const void *priv) +VRT_init_dir(struct cli *cli, struct director **bp, int idx, const void *priv) { const struct vrt_backend *t; struct vdi_simple *vs; @@ -435,7 +438,6 @@ VRT_init_dir_simple(struct cli *cli, struct director **bp, int idx, vs->dir.name = "simple"; REPLACE(vs->dir.vcl_name, t->vcl_name); vs->dir.getfd = vdi_simple_getfd; - vs->dir.fini = vdi_simple_fini; vs->dir.healthy = vdi_simple_healthy; vs->vrt = t; diff --git a/bin/varnishd/cache/cache_backend.h b/bin/varnishd/cache/cache_backend.h index f3931e9..8ce403d 100644 --- a/bin/varnishd/cache/cache_backend.h +++ b/bin/varnishd/cache/cache_backend.h @@ -76,7 +76,6 @@ struct vrt_backend_probe; */ typedef struct vbc *vdi_getfd_f(const struct director *, struct busyobj *); -typedef void vdi_fini_f(const struct director *); typedef unsigned vdi_healthy(const struct director *, double *changed); struct director { @@ -85,7 +84,6 @@ struct director { const char *name; char *vcl_name; vdi_getfd_f *getfd; - vdi_fini_f *fini; vdi_healthy *healthy; void *priv; }; @@ -165,7 +163,3 @@ void VBP_Insert(struct backend *b, struct vrt_backend_probe const *p, void VBP_Remove(struct backend *b, struct vrt_backend_probe const *p); void VBP_Use(const struct backend *b, const struct vrt_backend_probe *p); void VBP_Summary(struct cli *cli, const struct vbp_target *vt); - -/* Init functions for directors */ -typedef void dir_init_f(struct cli *, struct director **, int , const void*); -dir_init_f VRT_init_dir_simple; diff --git a/bin/varnishd/cache/cache_backend_cfg.c b/bin/varnishd/cache/cache_backend_cfg.c index 2d55147..e451bc8 100644 --- a/bin/varnishd/cache/cache_backend_cfg.c +++ b/bin/varnishd/cache/cache_backend_cfg.c @@ -239,31 +239,6 @@ VBE_AddBackend(struct cli *cli, const struct vrt_backend *vb) return (b); } -/*--------------------------------------------------------------------*/ - -void -VRT_init_dir(struct cli *cli, struct director **dir, const char *name, - int idx, const void *priv) -{ - - ASSERT_CLI(); - if (!strcmp(name, "simple")) - VRT_init_dir_simple(cli, dir, idx, priv); - else - INCOMPL(); -} - -void -VRT_fini_dir(struct cli *cli, struct director *b) -{ - - (void)cli; - ASSERT_CLI(); - CHECK_OBJ_NOTNULL(b, DIRECTOR_MAGIC); - b->fini(b); - b->priv = NULL; -} - /*--------------------------------------------------------------------- * String to admin_health */ diff --git a/include/vrt.h b/include/vrt.h index 1d079fc..d229655 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -222,8 +222,7 @@ void VRT_Rollback(const struct vrt_ctx *); void VRT_synth_page(const struct vrt_ctx *, unsigned flags, const char *, ...); /* Backend related */ -void VRT_init_dir(struct cli *, struct director **, const char *name, - int idx, const void *priv); +void VRT_init_dir(struct cli *, struct director **, int idx, const void *priv); void VRT_fini_dir(struct cli *, struct director *); /* VMOD/Modules related */ diff --git a/lib/libvcl/vcc_backend.c b/lib/libvcl/vcc_backend.c index b013400..1f95772 100644 --- a/lib/libvcl/vcc_backend.c +++ b/lib/libvcl/vcc_backend.c @@ -444,7 +444,7 @@ vcc_ParseHostDef(struct vcc *tl, int serial, const char *vgcname) Fh(tl, 0, "%s", VSB_data(vsb)); VSB_delete(vsb); - Fi(tl, 0, "\tVRT_init_dir(cli, VCL_conf.director, \"simple\",\n" + Fi(tl, 0, "\tVRT_init_dir(cli, VCL_conf.director,\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++; From daghf at varnish-cache.org Tue Sep 10 10:51:25 2013 From: daghf at varnish-cache.org (Dag Haavi Finstad) Date: Tue, 10 Sep 2013 12:51:25 +0200 Subject: [master] 507d14a Remove unnecessary casts to non-const to fix -Werror=cast-qual issue during make distcheck Message-ID: commit 507d14a1a9750fb7e27429625bc499a92a71e018 Author: Dag Haavi Finstad Date: Mon Sep 9 17:28:01 2013 +0200 Remove unnecessary casts to non-const to fix -Werror=cast-qual issue during make distcheck diff --git a/lib/libvgz/infback.c b/lib/libvgz/infback.c index f3833c2..4cffcc7 100644 --- a/lib/libvgz/infback.c +++ b/lib/libvgz/infback.c @@ -317,7 +317,7 @@ void FAR *out_desc; state->mode = TABLE; break; case 3: - strm->msg = (char *)"invalid block type"; + strm->msg = "invalid block type"; state->mode = BAD; } DROPBITS(2); @@ -328,7 +328,7 @@ void FAR *out_desc; BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; + strm->msg = "invalid stored block lengths"; state->mode = BAD; break; } @@ -366,7 +366,7 @@ void FAR *out_desc; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; + strm->msg = "too many length or distance symbols"; state->mode = BAD; break; } @@ -388,7 +388,7 @@ void FAR *out_desc; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid code lengths set"; + strm->msg = "invalid code lengths set"; state->mode = BAD; break; } @@ -411,7 +411,7 @@ void FAR *out_desc; NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; + strm->msg = "invalid bit length repeat"; state->mode = BAD; break; } @@ -434,7 +434,7 @@ void FAR *out_desc; DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; + strm->msg = "invalid bit length repeat"; state->mode = BAD; break; } @@ -448,7 +448,7 @@ void FAR *out_desc; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; + strm->msg = "invalid code -- missing end-of-block"; state->mode = BAD; break; } @@ -462,7 +462,7 @@ void FAR *out_desc; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; + strm->msg = "invalid literal/lengths set"; state->mode = BAD; break; } @@ -471,7 +471,7 @@ void FAR *out_desc; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { - strm->msg = (char *)"invalid distances set"; + strm->msg = "invalid distances set"; state->mode = BAD; break; } @@ -529,7 +529,7 @@ void FAR *out_desc; /* invalid code */ if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; + strm->msg = "invalid literal/length code"; state->mode = BAD; break; } @@ -561,7 +561,7 @@ void FAR *out_desc; } DROPBITS(here.bits); if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; + strm->msg = "invalid distance code"; state->mode = BAD; break; } @@ -576,7 +576,7 @@ void FAR *out_desc; } if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = "invalid distance too far back"; state->mode = BAD; break; } diff --git a/lib/libvgz/inffast.c b/lib/libvgz/inffast.c index bda59ce..73aecb9 100644 --- a/lib/libvgz/inffast.c +++ b/lib/libvgz/inffast.c @@ -175,7 +175,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ dist += (unsigned)hold & ((1U << op) - 1); #ifdef INFLATE_STRICT if (dist > dmax) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = "invalid distance too far back"; state->mode = BAD; break; } @@ -189,7 +189,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ if (op > whave) { if (state->sane) { strm->msg = - (char *)"invalid distance too far back"; + "invalid distance too far back"; state->mode = BAD; break; } @@ -285,7 +285,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ goto dodist; } else { - strm->msg = (char *)"invalid distance code"; + strm->msg = "invalid distance code"; state->mode = BAD; break; } @@ -300,7 +300,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ break; } else { - strm->msg = (char *)"invalid literal/length code"; + strm->msg = "invalid literal/length code"; state->mode = BAD; break; } diff --git a/lib/libvgz/inflate.c b/lib/libvgz/inflate.c index 11f7207..e3e9fce 100644 --- a/lib/libvgz/inflate.c +++ b/lib/libvgz/inflate.c @@ -660,12 +660,12 @@ int flush; if ( #endif ((BITS(8) << 8) + (hold >> 8)) % 31) { - strm->msg = (char *)"incorrect header check"; + strm->msg = "incorrect header check"; state->mode = BAD; break; } if (BITS(4) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; + strm->msg = "unknown compression method"; state->mode = BAD; break; } @@ -674,7 +674,7 @@ int flush; if (state->wbits == 0) state->wbits = len; else if (len > state->wbits) { - strm->msg = (char *)"invalid window size"; + strm->msg = "invalid window size"; state->mode = BAD; break; } @@ -689,12 +689,12 @@ int flush; NEEDBITS(16); state->flags = (int)(hold); if ((state->flags & 0xff) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; + strm->msg = "unknown compression method"; state->mode = BAD; break; } if (state->flags & 0xe000) { - strm->msg = (char *)"unknown header flags set"; + strm->msg = "unknown header flags set"; state->mode = BAD; break; } @@ -798,7 +798,7 @@ int flush; if (state->flags & 0x0200) { NEEDBITS(16); if (hold != (state->check & 0xffff)) { - strm->msg = (char *)"header crc mismatch"; + strm->msg = "header crc mismatch"; state->mode = BAD; break; } @@ -862,7 +862,7 @@ int flush; state->mode = TABLE; break; case 3: - strm->msg = (char *)"invalid block type"; + strm->msg = "invalid block type"; state->mode = BAD; } DROPBITS(2); @@ -871,7 +871,7 @@ int flush; BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; + strm->msg = "invalid stored block lengths"; state->mode = BAD; break; } @@ -910,7 +910,7 @@ int flush; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; + strm->msg = "too many length or distance symbols"; state->mode = BAD; break; } @@ -932,7 +932,7 @@ int flush; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid code lengths set"; + strm->msg = "invalid code lengths set"; state->mode = BAD; break; } @@ -955,7 +955,7 @@ int flush; NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; + strm->msg = "invalid bit length repeat"; state->mode = BAD; break; } @@ -978,7 +978,7 @@ int flush; DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; + strm->msg = "invalid bit length repeat"; state->mode = BAD; break; } @@ -992,7 +992,7 @@ int flush; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; + strm->msg = "invalid code -- missing end-of-block"; state->mode = BAD; break; } @@ -1006,7 +1006,7 @@ int flush; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; + strm->msg = "invalid literal/lengths set"; state->mode = BAD; break; } @@ -1015,7 +1015,7 @@ int flush; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { - strm->msg = (char *)"invalid distances set"; + strm->msg = "invalid distances set"; state->mode = BAD; break; } @@ -1067,7 +1067,7 @@ int flush; break; } if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; + strm->msg = "invalid literal/length code"; state->mode = BAD; break; } @@ -1103,7 +1103,7 @@ int flush; DROPBITS(here.bits); state->back += here.bits; if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; + strm->msg = "invalid distance code"; state->mode = BAD; break; } @@ -1119,7 +1119,7 @@ int flush; } #ifdef INFLATE_STRICT if (state->offset > state->dmax) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = "invalid distance too far back"; state->mode = BAD; break; } @@ -1133,7 +1133,7 @@ int flush; copy = state->offset - copy; if (copy > state->whave) { if (state->sane) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = "invalid distance too far back"; state->mode = BAD; break; } @@ -1192,7 +1192,7 @@ int flush; state->flags ? hold : #endif ZSWAP32(hold)) != state->check) { - strm->msg = (char *)"incorrect data check"; + strm->msg = "incorrect data check"; state->mode = BAD; break; } @@ -1205,7 +1205,7 @@ int flush; if (state->wrap && state->flags) { NEEDBITS(32); if (hold != (state->total & 0xffffffffUL)) { - strm->msg = (char *)"incorrect length check"; + strm->msg = "incorrect length check"; state->mode = BAD; break; } From phk at varnish-cache.org Tue Sep 10 10:57:27 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 10 Sep 2013 12:57:27 +0200 Subject: [master] f217f3e Be more consistent about using the VCL typedefs Message-ID: commit f217f3ebb72bd665bf0f2a113e336bc2ea1939aa Author: Poul-Henning Kamp Date: Tue Sep 10 10:57:04 2013 +0000 Be more consistent about using the VCL typedefs diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c index e4aecb1..974bbd7 100644 --- a/bin/varnishd/cache/cache_vrt.c +++ b/bin/varnishd/cache/cache_vrt.c @@ -297,24 +297,26 @@ VRT_r_now(const struct vrt_ctx *ctx) /*--------------------------------------------------------------------*/ char * -VRT_IP_string(const struct vrt_ctx *ctx, const struct sockaddr_storage *sa) +VRT_IP_string(const struct vrt_ctx *ctx, const VCL_IP ip) { char *p; + const struct sockaddr *sa; const struct sockaddr_in *si4; const struct sockaddr_in6 *si6; const void *addr; int len; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); - switch (sa->ss_family) { + sa = ip; + switch (sa->sa_family) { case AF_INET: len = INET_ADDRSTRLEN; - si4 = (const void *)sa; + si4 = ip; addr = &(si4->sin_addr); break; case AF_INET6: len = INET6_ADDRSTRLEN; - si6 = (const void *)sa; + si6 = ip; addr = &(si6->sin6_addr); break; default: @@ -322,7 +324,7 @@ VRT_IP_string(const struct vrt_ctx *ctx, const struct sockaddr_storage *sa) } XXXAN(len); AN(p = WS_Alloc(ctx->ws, len)); - AN(inet_ntop(sa->ss_family, addr, p, len)); + AN(inet_ntop(sa->sa_family, addr, p, len)); return (p); } @@ -364,8 +366,8 @@ VRT_TIME_string(const struct vrt_ctx *ctx, double t) return (p); } -const char * -VRT_BACKEND_string(const struct director *d) +const char * __match_proto__() +VRT_BACKEND_string(VCL_BACKEND d) { if (d == NULL) return (NULL); diff --git a/include/vrt.h b/include/vrt.h index d229655..7d03c47 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -252,10 +252,10 @@ int VRT_Stv(const char *nm); /* Convert things to string */ -char *VRT_IP_string(const struct vrt_ctx *, const struct sockaddr_storage *sa); -char *VRT_INT_string(const struct vrt_ctx *, long); -char *VRT_REAL_string(const struct vrt_ctx *, double); -char *VRT_TIME_string(const struct vrt_ctx *, double); -const char *VRT_BOOL_string(unsigned); -const char *VRT_BACKEND_string(const struct director *d); +char *VRT_IP_string(const struct vrt_ctx *, VCL_IP); +char *VRT_INT_string(const struct vrt_ctx *, VCL_INT); +char *VRT_REAL_string(const struct vrt_ctx *, VCL_REAL); +char *VRT_TIME_string(const struct vrt_ctx *, VCL_TIME); +const char *VRT_BOOL_string(VCL_BOOL); +const char *VRT_BACKEND_string(VCL_BACKEND); const char *VRT_CollectString(const struct vrt_ctx *, const char *p, ...); From phk at varnish-cache.org Wed Sep 11 06:05:10 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 11 Sep 2013 08:05:10 +0200 Subject: [master] 0cdfda9 Now that directors are in VMODs and VCL_BACKEND is a bona fide VCL type, we can simplify the VCC backend code somewhat. Message-ID: commit 0cdfda9387e93b7fcb02f3db5cf4d282b1e06524 Author: Poul-Henning Kamp Date: Wed Sep 11 06:04:26 2013 +0000 Now that directors are in VMODs and VCL_BACKEND is a bona fide VCL type, we can simplify the VCC backend code somewhat. diff --git a/lib/libvcl/vcc_backend.c b/lib/libvcl/vcc_backend.c index 1f95772..95e934e 100644 --- a/lib/libvcl/vcc_backend.c +++ b/lib/libvcl/vcc_backend.c @@ -26,26 +26,6 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * A necessary explanation of a convoluted policy: - * - * In VCL we have backends and directors. - * - * In VRT we have directors which reference (a number of) backend hosts. - * - * A VCL backend therefore has an implicit director of type "simple" created - * by the compiler, but not visible in VCL. - * - * A VCL backend is a "named host", these can be referenced by name from - * VCL directors, but not from VCL backends. - * - * The reason for this quasimadness is that we want to collect statistics - * for each actual kickable hardware backend machine, but we want to be - * able to refer to them multiple times in different directors. - * - * At the same time, we do not want to force users to declare each backend - * host with a name, if all they want to do is put it into a director, so - * backend hosts can be declared inline in the director, in which case - * its identity is the director and its numerical index therein. */ #include "config.h" @@ -57,13 +37,6 @@ #include "vss.h" -struct host { - VTAILQ_ENTRY(host) list; - struct token *name; - char *vgcname; -}; - - /*-------------------------------------------------------------------- * Struct sockaddr is not really designed to be a compile time * initialized data structure, so we encode it as a byte-string @@ -293,7 +266,7 @@ vcc_ParseProbe(struct vcc *tl) */ static void -vcc_ParseHostDef(struct vcc *tl, int serial, const char *vgcname) +vcc_ParseHostDef(struct vcc *tl, const struct token *t_be) { struct token *t_field; struct token *t_host = NULL; @@ -303,6 +276,9 @@ vcc_ParseHostDef(struct vcc *tl, int serial, const char *vgcname) struct vsb *vsb; unsigned u; double t; + char vgcname[MAX_BACKEND_NAME + 8]; + + sprintf(vgcname, "_%.*s", PF(t_be)); Fh(tl, 1, "\n#define VGC_backend_%s %d\n", vgcname, tl->ndirector); @@ -326,9 +302,7 @@ vcc_ParseHostDef(struct vcc *tl, int serial, const char *vgcname) 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, "\t.vcl_name = \"%.*s", PF(t_be)); Fb(tl, 0, "\",\n"); /* Check for old syntax */ @@ -451,85 +425,51 @@ vcc_ParseHostDef(struct vcc *tl, int serial, const char *vgcname) } /*-------------------------------------------------------------------- - * Tell rest of compiler about a backend - */ - -static void -vcc_DefBackend(struct vcc *tl, const struct token *nm) -{ - struct symbol *sym; - - sym = VCC_GetSymbolTok(tl, nm, SYM_BACKEND); - AN(sym); - if (sym->ndef > 0) { - VSB_printf(tl->sb, "Backend %.*s redefined\n", PF(nm)); - vcc_ErrWhere(tl, nm); - return; - } - sym->fmt = BACKEND; - sym->eval = vcc_Eval_Backend; - sym->ndef++; -} - -/*-------------------------------------------------------------------- - * Parse a plain backend aka a simple director - */ - -static void -vcc_ParseSimpleDirector(struct vcc *tl) -{ - struct host *h; - char vgcname[BUFSIZ]; - - h = TlAlloc(tl, sizeof *h); - h->name = tl->t_dir; - vcc_DefBackend(tl, tl->t_dir); - ERRCHK(tl); - sprintf(vgcname, "_%.*s", PF(h->name)); - h->vgcname = TlAlloc(tl, strlen(vgcname) + 1); - strcpy(h->vgcname, vgcname); - - vcc_ParseHostDef(tl, -1, vgcname); - ERRCHK(tl); - - VTAILQ_INSERT_TAIL(&tl->hosts, h, list); -} - -/*-------------------------------------------------------------------- * Parse directors and backends */ void -vcc_ParseDirector(struct vcc *tl) +vcc_ParseBackend(struct vcc *tl) { - struct token *t_first; + struct token *t_first, *t_be; int isfirst; + struct symbol *sym; t_first = tl->t; - vcc_NextToken(tl); /* ID: director | backend */ + vcc_NextToken(tl); /* ID: backend */ vcc_ExpectCid(tl); /* ID: name */ ERRCHK(tl); - if (tl->t->e - tl->t->b > 64) { + + if (tl->t->e - tl->t->b > MAX_BACKEND_NAME) { VSB_printf(tl->sb, - "Name of %.*s too long (max 64, is %zu):\n", - PF(t_first), (size_t)(tl->t->e - tl->t->b)); + "Name of %.*s too long (max %d, is %zu):\n", + PF(t_first), MAX_BACKEND_NAME, + (size_t)(tl->t->e - tl->t->b)); vcc_ErrWhere(tl, tl->t); return; } - tl->t_dir = tl->t; - vcc_NextToken(tl); + t_be = tl->t; + vcc_NextToken(tl); isfirst = tl->ndirector; - if (vcc_IdIs(t_first, "backend")) { - vcc_ParseSimpleDirector(tl); - } else { - VSB_printf(tl->sb, - "\ndirectors are now in VMOD.directors\n"); - vcc_ErrWhere(tl, t_first); + + sym = VCC_GetSymbolTok(tl, t_be, SYM_BACKEND); + AN(sym); + if (sym->ndef > 0) { + VSB_printf(tl->sb, "Backend %.*s redefined\n", PF(t_be)); + vcc_ErrWhere(tl, t_be); return; } + sym->fmt = BACKEND; + sym->eval = vcc_Eval_Backend; + sym->ndef++; + ERRCHK(tl); + + vcc_ParseHostDef(tl, t_be); + ERRCHK(tl); + if (tl->err) { VSB_printf(tl->sb, "\nIn %.*s specification starting at:\n", PF(t_first)); @@ -537,10 +477,8 @@ vcc_ParseDirector(struct vcc *tl) return; } - if (isfirst == 1 || vcc_IdIs(tl->t_dir, "default")) { + if (isfirst == 1 || vcc_IdIs(t_be, "default")) { tl->defaultdir = tl->ndirector - 1; - tl->t_defaultdir = tl->t_dir; + tl->t_defaultdir = t_be; } - - tl->t_dir = NULL; } diff --git a/lib/libvcl/vcc_compile.c b/lib/libvcl/vcc_compile.c index c34ffc4..eeb392c 100644 --- a/lib/libvcl/vcc_compile.c +++ b/lib/libvcl/vcc_compile.c @@ -517,7 +517,6 @@ vcc_NewVcc(const struct vcc *tl0) tl->err_unref = 1; } VTAILQ_INIT(&tl->symbols); - VTAILQ_INIT(&tl->hosts); VTAILQ_INIT(&tl->membits); VTAILQ_INIT(&tl->tokens); VTAILQ_INIT(&tl->sources); diff --git a/lib/libvcl/vcc_compile.h b/lib/libvcl/vcc_compile.h index 1b6da33..65401df 100644 --- a/lib/libvcl/vcc_compile.h +++ b/lib/libvcl/vcc_compile.h @@ -160,7 +160,6 @@ struct vcc { struct tokenhead tokens; VTAILQ_HEAD(, source) sources; VTAILQ_HEAD(, membit) membits; - VTAILQ_HEAD(, host) hosts; unsigned nsources; struct source *src; struct token *t; @@ -191,7 +190,6 @@ struct vcc { int defaultdir; struct token *t_defaultdir; - struct token *t_dir; unsigned unique; unsigned nvmodpriv; @@ -228,10 +226,11 @@ void vcc_Acl_Hack(struct vcc *tl, char *b); int vcc_ParseAction(struct vcc *tl); /* vcc_backend.c */ +#define MAX_BACKEND_NAME 64 struct fld_spec; void vcc_ParseProbe(struct vcc *tl); -void vcc_ParseDirector(struct vcc *tl); +void vcc_ParseBackend(struct vcc *tl); struct fld_spec * vcc_FldSpec(struct vcc *tl, const char *first, ...); void vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs); void vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs); diff --git a/lib/libvcl/vcc_parse.c b/lib/libvcl/vcc_parse.c index e334846..abe07ee 100644 --- a/lib/libvcl/vcc_parse.c +++ b/lib/libvcl/vcc_parse.c @@ -274,6 +274,16 @@ vcc_Function(struct vcc *tl) } /*-------------------------------------------------------------------- + */ + +static void +vcc_Director(struct vcc *tl) +{ + VSB_printf(tl->sb, "\ndirectors are now in directors VMOD.\n"); + vcc_ErrWhere(tl, tl->t); +} + +/*-------------------------------------------------------------------- * Top level of parser, recognize: * Inline C-code * ACL definitions @@ -290,8 +300,8 @@ static struct toplev { } toplev[] = { { "acl", vcc_Acl }, { "sub", vcc_Function }, - { "backend", vcc_ParseDirector }, - { "director", vcc_ParseDirector }, + { "backend", vcc_ParseBackend }, + { "director", vcc_Director }, { "probe", vcc_ParseProbe }, { "import", vcc_ParseImport }, { NULL, NULL } From phk at varnish-cache.org Wed Sep 11 06:29:08 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 11 Sep 2013 08:29:08 +0200 Subject: [master] 2bf6743 Update copyright notices in preparation for release Message-ID: commit 2bf67435c14dff4406001eb565264009fff25e8d Author: Poul-Henning Kamp Date: Wed Sep 11 06:28:44 2013 +0000 Update copyright notices in preparation for release diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index b0747cc..c911933 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_acceptor.c b/bin/varnishd/cache/cache_acceptor.c index e7de0b3..bfaabca 100644 --- a/bin/varnishd/cache/cache_acceptor.c +++ b/bin/varnishd/cache/cache_acceptor.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c index a7dfd2a..0b8b387 100644 --- a/bin/varnishd/cache/cache_backend.c +++ b/bin/varnishd/cache/cache_backend.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_backend.h b/bin/varnishd/cache/cache_backend.h index 8ce403d..265073b 100644 --- a/bin/varnishd/cache/cache_backend.h +++ b/bin/varnishd/cache/cache_backend.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_backend_cfg.c b/bin/varnishd/cache/cache_backend_cfg.c index e451bc8..c217845 100644 --- a/bin/varnishd/cache/cache_backend_cfg.c +++ b/bin/varnishd/cache/cache_backend_cfg.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_busyobj.c b/bin/varnishd/cache/cache_busyobj.c index 01f0a33..ca721b7 100644 --- a/bin/varnishd/cache/cache_busyobj.c +++ b/bin/varnishd/cache/cache_busyobj.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011 Varnish Software AS + * Copyright (c) 2013 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/bin/varnishd/cache/cache_dir.c b/bin/varnishd/cache/cache_dir.c index ae6cb2d..2e10dcc 100644 --- a/bin/varnishd/cache/cache_dir.c +++ b/bin/varnishd/cache/cache_dir.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index a79e6cc..acff988 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_fetch_proc.c b/bin/varnishd/cache/cache_fetch_proc.c index 2871b73..c7d1dcd 100644 --- a/bin/varnishd/cache/cache_fetch_proc.c +++ b/bin/varnishd/cache/cache_fetch_proc.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_gzip.c b/bin/varnishd/cache/cache_gzip.c index 6eab8a4..a95c4d4 100644 --- a/bin/varnishd/cache/cache_gzip.c +++ b/bin/varnishd/cache/cache_gzip.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011 Varnish Software AS + * Copyright (c) 2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c index 7171b53..b653d50 100644 --- a/bin/varnishd/cache/cache_hash.c +++ b/bin/varnishd/cache/cache_hash.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c index 3075fea..f9d0372 100644 --- a/bin/varnishd/cache/cache_http.c +++ b/bin/varnishd/cache/cache_http.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_http1_fetch.c b/bin/varnishd/cache/cache_http1_fetch.c index d15d6c9..2620912 100644 --- a/bin/varnishd/cache/cache_http1_fetch.c +++ b/bin/varnishd/cache/cache_http1_fetch.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_http1_fsm.c b/bin/varnishd/cache/cache_http1_fsm.c index d77c36e..85e3022 100644 --- a/bin/varnishd/cache/cache_http1_fsm.c +++ b/bin/varnishd/cache/cache_http1_fsm.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_http1_proto.c b/bin/varnishd/cache/cache_http1_proto.c index 3371089..d59c384 100644 --- a/bin/varnishd/cache/cache_http1_proto.c +++ b/bin/varnishd/cache/cache_http1_proto.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_panic.c b/bin/varnishd/cache/cache_panic.c index ff70390..c79a1bb 100644 --- a/bin/varnishd/cache/cache_panic.c +++ b/bin/varnishd/cache/cache_panic.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Dag-Erling Sm?rgrav diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 34b8138..b2e2b72 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_shmlog.c b/bin/varnishd/cache/cache_shmlog.c index 5b33dad..0093c74 100644 --- a/bin/varnishd/cache/cache_shmlog.c +++ b/bin/varnishd/cache/cache_shmlog.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_vary.c b/bin/varnishd/cache/cache_vary.c index 08736c6..9dddf60 100644 --- a/bin/varnishd/cache/cache_vary.c +++ b/bin/varnishd/cache/cache_vary.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_vcl.c b/bin/varnishd/cache/cache_vcl.c index 96288b6..b342f43 100644 --- a/bin/varnishd/cache/cache_vcl.c +++ b/bin/varnishd/cache/cache_vcl.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c index 974bbd7..d137c19 100644 --- a/bin/varnishd/cache/cache_vrt.c +++ b/bin/varnishd/cache/cache_vrt.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_vrt_re.c b/bin/varnishd/cache/cache_vrt_re.c index 856a057..1248114 100644 --- a/bin/varnishd/cache/cache_vrt_re.c +++ b/bin/varnishd/cache/cache_vrt_re.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_vrt_var.c b/bin/varnishd/cache/cache_vrt_var.c index f72586e..a1c35f0 100644 --- a/bin/varnishd/cache/cache_vrt_var.c +++ b/bin/varnishd/cache/cache_vrt_var.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/cache/cache_vrt_vmod.c b/bin/varnishd/cache/cache_vrt_vmod.c index dea71ff..84fb105 100644 --- a/bin/varnishd/cache/cache_vrt_vmod.c +++ b/bin/varnishd/cache/cache_vrt_vmod.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/default.vcl b/bin/varnishd/default.vcl index 46d3a21..50e5da2 100644 --- a/bin/varnishd/default.vcl +++ b/bin/varnishd/default.vcl @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/hash/hash_slinger.h b/bin/varnishd/hash/hash_slinger.h index cbe7082..a72e425 100644 --- a/bin/varnishd/hash/hash_slinger.h +++ b/bin/varnishd/hash/hash_slinger.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/mgt/mgt_child.c b/bin/varnishd/mgt/mgt_child.c index 850dc4a..aa66c5a 100644 --- a/bin/varnishd/mgt/mgt_child.c +++ b/bin/varnishd/mgt/mgt_child.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishd/storage/stevedore.c b/bin/varnishd/storage/stevedore.c index 2d64d2d..a7d0b44 100644 --- a/bin/varnishd/storage/stevedore.c +++ b/bin/varnishd/storage/stevedore.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2007-2011 Varnish Software AS + * Copyright (c) 2007-2013 Varnish Software AS * All rights reserved. * * Author: Dag-Erling Sm?rgav diff --git a/bin/varnishd/waiter/cache_waiter.c b/bin/varnishd/waiter/cache_waiter.c index 1b868fe..d3d97dc 100644 --- a/bin/varnishd/waiter/cache_waiter.c +++ b/bin/varnishd/waiter/cache_waiter.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishlog/varnishlog.c b/bin/varnishlog/varnishlog.c index d3d9e29..6c40902 100644 --- a/bin/varnishlog/varnishlog.c +++ b/bin/varnishlog/varnishlog.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishlog/varnishlog_options.c b/bin/varnishlog/varnishlog_options.c index 4b5037d..83255c5 100644 --- a/bin/varnishlog/varnishlog_options.c +++ b/bin/varnishlog/varnishlog_options.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/bin/varnishlog/varnishlog_options.h b/bin/varnishlog/varnishlog_options.h index 5c09c58..84f84da 100644 --- a/bin/varnishlog/varnishlog_options.h +++ b/bin/varnishlog/varnishlog_options.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/bin/varnishstat/varnishstat_curses.c b/bin/varnishstat/varnishstat_curses.c index 16df1b4..1fca651 100644 --- a/bin/varnishstat/varnishstat_curses.c +++ b/bin/varnishstat/varnishstat_curses.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishtest/tests/v00021.vtc b/bin/varnishtest/tests/v00021.vtc index a8c20b5..636207e 100644 --- a/bin/varnishtest/tests/v00021.vtc +++ b/bin/varnishtest/tests/v00021.vtc @@ -66,7 +66,7 @@ varnish v1 -errvcl {Invalid return "deliver"} { } } -varnish v1 -errvcl {directors are now in VMOD.directors} { +varnish v1 -errvcl {directors are now in directors VMOD} { backend b { .host = "127.0.0.1"; } director d1 random { diff --git a/bin/varnishtest/vtc_http.c b/bin/varnishtest/vtc_http.c index 7959b74..cf51baf 100644 --- a/bin/varnishtest/vtc_http.c +++ b/bin/varnishtest/vtc_http.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008-2011 Varnish Software AS + * Copyright (c) 2008-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishtest/vtc_logexp.c b/bin/varnishtest/vtc_logexp.c index a5cbf86..56539e6 100644 --- a/bin/varnishtest/vtc_logexp.c +++ b/bin/varnishtest/vtc_logexp.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008-2013 Varnish Software AS + * Copyright (c) 2008-2011 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/bin/varnishtest/vtc_varnish.c b/bin/varnishtest/vtc_varnish.c index 2c81be1..ff8cfa2 100644 --- a/bin/varnishtest/vtc_varnish.c +++ b/bin/varnishtest/vtc_varnish.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008-2011 Varnish Software AS + * Copyright (c) 2008-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/configure.ac b/configure.ac index a43f209..0bd07b6 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ(2.59) AC_COPYRIGHT([Copyright (c) 2006 Verdens Gang AS -Copyright (c) 2006-2011 Varnish Software AS]) +Copyright (c) 2006-2013 Varnish Software AS]) AC_REVISION([$Id$]) AC_INIT([Varnish], [trunk], [varnish-dev at varnish-cache.org]) AC_CONFIG_SRCDIR(include/miniobj.h) diff --git a/include/tbl/steps.h b/include/tbl/steps.h index 34a2315..886f4ac 100644 --- a/include/tbl/steps.h +++ b/include/tbl/steps.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/tbl/symbol_kind.h b/include/tbl/symbol_kind.h index 3d426f9..0a67e12 100644 --- a/include/tbl/symbol_kind.h +++ b/include/tbl/symbol_kind.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2010 Varnish Software AS + * Copyright (c) 2010-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/tbl/vsc_all.h b/include/tbl/vsc_all.h index deb5eaf..927e0fb 100644 --- a/include/tbl/vsc_all.h +++ b/include/tbl/vsc_all.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2010 Varnish Software AS + * Copyright (c) 2010-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/tbl/vsc_f_main.h b/include/tbl/vsc_f_main.h index a42579b..3504b57 100644 --- a/include/tbl/vsc_f_main.h +++ b/include/tbl/vsc_f_main.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/tbl/vsc_fields.h b/include/tbl/vsc_fields.h index 85fe2e4..a523c24 100644 --- a/include/tbl/vsc_fields.h +++ b/include/tbl/vsc_fields.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/tbl/vsl_tags.h b/include/tbl/vsl_tags.h index 827a231..c2fb6d9 100644 --- a/include/tbl/vsl_tags.h +++ b/include/tbl/vsl_tags.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2010 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/vapi/vapi_options.h b/include/vapi/vapi_options.h index df3dc83..52ffb74 100644 --- a/include/vapi/vapi_options.h +++ b/include/vapi/vapi_options.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/include/vapi/voptget.h b/include/vapi/voptget.h index 4f30848..2e5023a 100644 --- a/include/vapi/voptget.h +++ b/include/vapi/voptget.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/include/vapi/vsc_int.h b/include/vapi/vsc_int.h index 3583d2b..88d851a 100644 --- a/include/vapi/vsc_int.h +++ b/include/vapi/vsc_int.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2010 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/vapi/vsl.h b/include/vapi/vsl.h index b5d10f8..0e434d0 100644 --- a/include/vapi/vsl.h +++ b/include/vapi/vsl.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/vapi/vsl_int.h b/include/vapi/vsl_int.h index 419af70..cce354a 100644 --- a/include/vapi/vsl_int.h +++ b/include/vapi/vsl_int.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2010 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/vdef.h b/include/vdef.h index 2a0addb..8fef2b1 100644 --- a/include/vdef.h +++ b/include/vdef.h @@ -1,7 +1,7 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2012 Varnish Software AS * Copyright (c) 2012 Fastly Inc + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/vrt.h b/include/vrt.h index 7d03c47..203bba1 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2010 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/vut.h b/include/vut.h index 0fdf8de..f102b36 100644 --- a/include/vut.h +++ b/include/vut.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/include/vut_options.h b/include/vut_options.h index 3034b41..369358c 100644 --- a/include/vut_options.h +++ b/include/vut_options.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/lib/libvarnish/vtcp.c b/lib/libvarnish/vtcp.c index 6b9df11..b33d306 100644 --- a/lib/libvarnish/vtcp.c +++ b/lib/libvarnish/vtcp.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvarnishapi/vsl.c b/lib/libvarnishapi/vsl.c index d7a5fa8..1dea1d0 100644 --- a/lib/libvarnishapi/vsl.c +++ b/lib/libvarnishapi/vsl.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvarnishapi/vsl_api.h b/lib/libvarnishapi/vsl_api.h index 46f5004..edb5651 100644 --- a/lib/libvarnishapi/vsl_api.h +++ b/lib/libvarnishapi/vsl_api.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvarnishapi/vsl_cursor.c b/lib/libvarnishapi/vsl_cursor.c index c4f3cf1..42616b6 100644 --- a/lib/libvarnishapi/vsl_cursor.c +++ b/lib/libvarnishapi/vsl_cursor.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvarnishapi/vsl_dispatch.c b/lib/libvarnishapi/vsl_dispatch.c index bb2da3f..a36545d 100644 --- a/lib/libvarnishapi/vsl_dispatch.c +++ b/lib/libvarnishapi/vsl_dispatch.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/lib/libvarnishapi/vsl_query.c b/lib/libvarnishapi/vsl_query.c index 436d7c9..7d896a8 100644 --- a/lib/libvarnishapi/vsl_query.c +++ b/lib/libvarnishapi/vsl_query.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/lib/libvarnishtools/opt2rst.c b/lib/libvarnishtools/opt2rst.c index 68d5200..4bee4b6 100644 --- a/lib/libvarnishtools/opt2rst.c +++ b/lib/libvarnishtools/opt2rst.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/lib/libvarnishtools/vut.c b/lib/libvarnishtools/vut.c index d3e5abd..b5a4c58 100644 --- a/lib/libvarnishtools/vut.c +++ b/lib/libvarnishtools/vut.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS + * Copyright (c) 2006-2011 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/lib/libvcl/generate.py b/lib/libvcl/generate.py index 979f2b1..36be27b 100755 --- a/lib/libvcl/generate.py +++ b/lib/libvcl/generate.py @@ -1,7 +1,7 @@ #!/usr/local/bin/python3.1 #- # Copyright (c) 2006 Verdens Gang AS -# Copyright (c) 2006-2011 Varnish Software AS +# Copyright (c) 2006-2013 Varnish Software AS # All rights reserved. # # Author: Poul-Henning Kamp diff --git a/lib/libvcl/vcc_action.c b/lib/libvcl/vcc_action.c index 1b31fb7..4e441d2 100644 --- a/lib/libvcl/vcc_action.c +++ b/lib/libvcl/vcc_action.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvcl/vcc_backend.c b/lib/libvcl/vcc_backend.c index 95e934e..b548d94 100644 --- a/lib/libvcl/vcc_backend.c +++ b/lib/libvcl/vcc_backend.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvcl/vcc_compile.c b/lib/libvcl/vcc_compile.c index eeb392c..07eef41 100644 --- a/lib/libvcl/vcc_compile.c +++ b/lib/libvcl/vcc_compile.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvcl/vcc_compile.h b/lib/libvcl/vcc_compile.h index 65401df..b0983cc 100644 --- a/lib/libvcl/vcc_compile.h +++ b/lib/libvcl/vcc_compile.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2010 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvcl/vcc_parse.c b/lib/libvcl/vcc_parse.c index abe07ee..ab562f5 100644 --- a/lib/libvcl/vcc_parse.c +++ b/lib/libvcl/vcc_parse.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvcl/vcc_utils.c b/lib/libvcl/vcc_utils.c index e75cf25..5870af5 100644 --- a/lib/libvcl/vcc_utils.c +++ b/lib/libvcl/vcc_utils.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvcl/vcc_vmod.c b/lib/libvcl/vcc_vmod.c index 23a3171..7eb9d32c 100644 --- a/lib/libvcl/vcc_vmod.c +++ b/lib/libvcl/vcc_vmod.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2010-2011 Varnish Software AS + * Copyright (c) 2010-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvcl/vmodtool.py b/lib/libvcl/vmodtool.py index d99d8c6..2b6db42 100755 --- a/lib/libvcl/vmodtool.py +++ b/lib/libvcl/vmodtool.py @@ -1,6 +1,6 @@ #!/usr/bin/env python #- -# Copyright (c) 2010-2011 Varnish Software AS +# Copyright (c) 2010-2013 Varnish Software AS # All rights reserved. # # Author: Poul-Henning Kamp diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc index a27e998..993c1bc 100644 --- a/lib/libvmod_debug/vmod.vcc +++ b/lib/libvmod_debug/vmod.vcc @@ -1,5 +1,5 @@ #- -# Copyright (c) 2010-2011 Varnish Software AS +# Copyright (c) 2010-2013 Varnish Software AS # All rights reserved. # # Author: Poul-Henning Kamp diff --git a/lib/libvmod_debug/vmod_debug.c b/lib/libvmod_debug/vmod_debug.c index 083962f..e864880 100644 --- a/lib/libvmod_debug/vmod_debug.c +++ b/lib/libvmod_debug/vmod_debug.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2012 Varnish Software AS + * Copyright (c) 2012-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvmod_std/vmod_std.c b/lib/libvmod_std/vmod_std.c index f105135..8926d3d 100644 --- a/lib/libvmod_std/vmod_std.c +++ b/lib/libvmod_std/vmod_std.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2010-2011 Varnish Software AS + * Copyright (c) 2010-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvmod_std/vmod_std_conversions.c b/lib/libvmod_std/vmod_std_conversions.c index 651a77c..68af3ad 100644 --- a/lib/libvmod_std/vmod_std_conversions.c +++ b/lib/libvmod_std/vmod_std_conversions.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2010-2011 Varnish Software AS + * Copyright (c) 2010-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp From phk at varnish-cache.org Wed Sep 11 06:45:34 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 11 Sep 2013 08:45:34 +0200 Subject: [master] baa0dd7 Remove counters related to DNS director. Message-ID: commit baa0dd7e2be6e4608db99283a9c71d2b756a1bf0 Author: Poul-Henning Kamp Date: Wed Sep 11 06:45:21 2013 +0000 Remove counters related to DNS director. diff --git a/include/tbl/vsc_f_main.h b/include/tbl/vsc_f_main.h index 3504b57..51ad0f6 100644 --- a/include/tbl/vsc_f_main.h +++ b/include/tbl/vsc_f_main.h @@ -552,25 +552,6 @@ VSC_F(esi_warnings, uint64_t, 0, 'a', diag, /*--------------------------------------------------------------------*/ -VSC_F(dir_dns_lookups, uint64_t, 0, 'a', diag, - "DNS director lookups", - "" -) -VSC_F(dir_dns_failed, uint64_t, 0, 'a', diag, - "DNS director failed lookups", - "" -) -VSC_F(dir_dns_hit, uint64_t, 0, 'a', diag, - "DNS director cached lookups hit", - "" -) -VSC_F(dir_dns_cache_full, uint64_t, 0, 'a', debug, - "DNS director full dnscache", - "" -) - -/*--------------------------------------------------------------------*/ - VSC_F(vmods, uint64_t, 0, 'i', info, "Loaded VMODs", "" From phk at varnish-cache.org Wed Sep 11 10:40:49 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 11 Sep 2013 12:40:49 +0200 Subject: [master] 2f7cf29 Count the number of times a threadpool runs against the upper limit Message-ID: commit 2f7cf2917239a8f0117945ff5b3d9b724d44dad9 Author: Poul-Henning Kamp Date: Wed Sep 11 10:40:26 2013 +0000 Count the number of times a threadpool runs against the upper limit diff --git a/bin/varnishd/cache/cache_pool.c b/bin/varnishd/cache/cache_pool.c index 4e7bd7c..4308fb3 100644 --- a/bin/varnishd/cache/cache_pool.c +++ b/bin/varnishd/cache/cache_pool.c @@ -404,8 +404,13 @@ pool_herder(void *priv) } Lck_Lock(&pp->mtx); - if (!pp->dry) + if (!pp->dry) { (void)Lck_CondWait(&pp->herder_cond, &pp->mtx, NULL); + } else { + /* XXX: unsafe counters */ + VSC_C_main->threads_limited++; + pp->dry = 0; + } Lck_Unlock(&pp->mtx); } NEEDLESS_RETURN(NULL); From martin at varnish-cache.org Wed Sep 11 12:54:39 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Wed, 11 Sep 2013 14:54:39 +0200 Subject: [master] 176d70c Add author to libvarnishapi files Message-ID: commit 176d70c32416ad80ab5e0d5f76cfc1b272207943 Author: Martin Blix Grydeland Date: Wed Sep 11 14:46:15 2013 +0200 Add author to libvarnishapi files Add author information to some files with significant changes. diff --git a/include/vapi/vsl_int.h b/include/vapi/vsl_int.h index cce354a..1689674 100644 --- a/include/vapi/vsl_int.h +++ b/include/vapi/vsl_int.h @@ -4,6 +4,7 @@ * All rights reserved. * * Author: Poul-Henning Kamp + * Author: Martin Blix Grydeland * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/include/vapi/vsm.h b/include/vapi/vsm.h index d4277a4..dd88bbb 100644 --- a/include/vapi/vsm.h +++ b/include/vapi/vsm.h @@ -4,6 +4,7 @@ * All rights reserved. * * Author: Poul-Henning Kamp + * Author: Martin Blix Grydeland * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/lib/libvarnishapi/vsc.c b/lib/libvarnishapi/vsc.c index c573fb8..921669b 100644 --- a/lib/libvarnishapi/vsc.c +++ b/lib/libvarnishapi/vsc.c @@ -4,6 +4,7 @@ * All rights reserved. * * Author: Poul-Henning Kamp + * Author: Martin Blix Grydeland * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/lib/libvarnishapi/vsl_arg.c b/lib/libvarnishapi/vsl_arg.c index c38d63d..cd0c4dc 100644 --- a/lib/libvarnishapi/vsl_arg.c +++ b/lib/libvarnishapi/vsl_arg.c @@ -4,6 +4,7 @@ * All rights reserved. * * Author: Poul-Henning Kamp + * Author: Martin Blix Grydeland * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/lib/libvarnishapi/vsm.c b/lib/libvarnishapi/vsm.c index 608443c..5f7af99 100644 --- a/lib/libvarnishapi/vsm.c +++ b/lib/libvarnishapi/vsm.c @@ -4,6 +4,7 @@ * All rights reserved. * * Author: Poul-Henning Kamp + * Author: Martin Blix Grydeland * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions From martin at varnish-cache.org Wed Sep 11 12:54:39 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Wed, 11 Sep 2013 14:54:39 +0200 Subject: [master] 970778c Update copyright dates in various files Message-ID: commit 970778c52ff7cd8bf54f7911e1dcecf844a74dbd Author: Martin Blix Grydeland Date: Wed Sep 11 14:51:45 2013 +0200 Update copyright dates in various files diff --git a/bin/varnishadm/varnishadm.c b/bin/varnishadm/varnishadm.c index 0e5706b..e7dc7ba 100644 --- a/bin/varnishadm/varnishadm.c +++ b/bin/varnishadm/varnishadm.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Cecilie Fritzvold diff --git a/bin/varnishlog/varnishlog.c b/bin/varnishlog/varnishlog.c index 6c40902..d3d9e29 100644 --- a/bin/varnishlog/varnishlog.c +++ b/bin/varnishlog/varnishlog.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishlog/varnishlog_options.c b/bin/varnishlog/varnishlog_options.c index 83255c5..4b5037d 100644 --- a/bin/varnishlog/varnishlog_options.c +++ b/bin/varnishlog/varnishlog_options.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/bin/varnishlog/varnishlog_options.h b/bin/varnishlog/varnishlog_options.h index 84f84da..5c09c58 100644 --- a/bin/varnishlog/varnishlog_options.h +++ b/bin/varnishlog/varnishlog_options.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/bin/varnishncsa/varnishncsa.c b/bin/varnishncsa/varnishncsa.c index da056ed..4674974 100644 --- a/bin/varnishncsa/varnishncsa.c +++ b/bin/varnishncsa/varnishncsa.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Anders Berg diff --git a/bin/varnishstat/varnishstat.c b/bin/varnishstat/varnishstat.c index 894710c..72ad021 100644 --- a/bin/varnishstat/varnishstat.c +++ b/bin/varnishstat/varnishstat.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishstat/varnishstat.h b/bin/varnishstat/varnishstat.h index 1f66476..2640fbd 100644 --- a/bin/varnishstat/varnishstat.h +++ b/bin/varnishstat/varnishstat.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2010-2011 Varnish Software AS + * Copyright (c) 2010-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishstat/varnishstat_curses.c b/bin/varnishstat/varnishstat_curses.c index 1fca651..16df1b4 100644 --- a/bin/varnishstat/varnishstat_curses.c +++ b/bin/varnishstat/varnishstat_curses.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/bin/varnishtest/vtc_logexp.c b/bin/varnishtest/vtc_logexp.c index 56539e6..a5cbf86 100644 --- a/bin/varnishtest/vtc_logexp.c +++ b/bin/varnishtest/vtc_logexp.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008-2011 Varnish Software AS + * Copyright (c) 2008-2013 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/include/vapi/vapi_options.h b/include/vapi/vapi_options.h index 52ffb74..df3dc83 100644 --- a/include/vapi/vapi_options.h +++ b/include/vapi/vapi_options.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/include/vapi/voptget.h b/include/vapi/voptget.h index 2e5023a..4f30848 100644 --- a/include/vapi/voptget.h +++ b/include/vapi/voptget.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/include/vapi/vsc.h b/include/vapi/vsc.h index 8fa7660..8ad7057 100644 --- a/include/vapi/vsc.h +++ b/include/vapi/vsc.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/vapi/vsc_int.h b/include/vapi/vsc_int.h index 88d851a..eaee691 100644 --- a/include/vapi/vsc_int.h +++ b/include/vapi/vsc_int.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/vapi/vsl_int.h b/include/vapi/vsl_int.h index 1689674..2d484f6 100644 --- a/include/vapi/vsl_int.h +++ b/include/vapi/vsl_int.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/vapi/vsm.h b/include/vapi/vsm.h index dd88bbb..04679b5 100644 --- a/include/vapi/vsm.h +++ b/include/vapi/vsm.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/vapi/vsm_int.h b/include/vapi/vsm_int.h index 2d1eab6..9305547 100644 --- a/include/vapi/vsm_int.h +++ b/include/vapi/vsm_int.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/include/vut.h b/include/vut.h index f102b36..0fdf8de 100644 --- a/include/vut.h +++ b/include/vut.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/include/vut_options.h b/include/vut_options.h index 369358c..3034b41 100644 --- a/include/vut_options.h +++ b/include/vut_options.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/lib/libvarnishapi/libvarnishapi.map b/lib/libvarnishapi/libvarnishapi.map index becda5d..384c0e1 100644 --- a/lib/libvarnishapi/libvarnishapi.map +++ b/lib/libvarnishapi/libvarnishapi.map @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011 Varnish Software AS + * Copyright (c) 2011-2013 Varnish Software AS * All rights reserved. * * Author: Tollef Fog Heen diff --git a/lib/libvarnishapi/vsc.c b/lib/libvarnishapi/vsc.c index 921669b..f2f270c 100644 --- a/lib/libvarnishapi/vsc.c +++ b/lib/libvarnishapi/vsc.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvarnishapi/vsl.c b/lib/libvarnishapi/vsl.c index 1dea1d0..d7a5fa8 100644 --- a/lib/libvarnishapi/vsl.c +++ b/lib/libvarnishapi/vsl.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvarnishapi/vsl_api.h b/lib/libvarnishapi/vsl_api.h index edb5651..46f5004 100644 --- a/lib/libvarnishapi/vsl_api.h +++ b/lib/libvarnishapi/vsl_api.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvarnishapi/vsl_arg.c b/lib/libvarnishapi/vsl_arg.c index cd0c4dc..00039ad 100644 --- a/lib/libvarnishapi/vsl_arg.c +++ b/lib/libvarnishapi/vsl_arg.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvarnishapi/vsl_cursor.c b/lib/libvarnishapi/vsl_cursor.c index 42616b6..c4f3cf1 100644 --- a/lib/libvarnishapi/vsl_cursor.c +++ b/lib/libvarnishapi/vsl_cursor.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvarnishapi/vsl_dispatch.c b/lib/libvarnishapi/vsl_dispatch.c index a36545d..bb2da3f 100644 --- a/lib/libvarnishapi/vsl_dispatch.c +++ b/lib/libvarnishapi/vsl_dispatch.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/lib/libvarnishapi/vsl_query.c b/lib/libvarnishapi/vsl_query.c index 7d896a8..436d7c9 100644 --- a/lib/libvarnishapi/vsl_query.c +++ b/lib/libvarnishapi/vsl_query.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/lib/libvarnishapi/vsm.c b/lib/libvarnishapi/vsm.c index 5f7af99..c62858d 100644 --- a/lib/libvarnishapi/vsm.c +++ b/lib/libvarnishapi/vsm.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvarnishapi/vsm_api.h b/lib/libvarnishapi/vsm_api.h index cc0b142..7431eed 100644 --- a/lib/libvarnishapi/vsm_api.h +++ b/lib/libvarnishapi/vsm_api.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp diff --git a/lib/libvarnishtools/opt2rst.c b/lib/libvarnishtools/opt2rst.c index 4bee4b6..68d5200 100644 --- a/lib/libvarnishtools/opt2rst.c +++ b/lib/libvarnishtools/opt2rst.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland diff --git a/lib/libvarnishtools/vut.c b/lib/libvarnishtools/vut.c index b5a4c58..d3e5abd 100644 --- a/lib/libvarnishtools/vut.c +++ b/lib/libvarnishtools/vut.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Martin Blix Grydeland From martin at varnish-cache.org Wed Sep 11 12:54:39 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Wed, 11 Sep 2013 14:54:39 +0200 Subject: [master] a7af8a2 Add missing copyright header and author information Message-ID: commit a7af8a2d4f7b47c4286651a165f4866ba7078cee Author: Martin Blix Grydeland Date: Wed Sep 11 14:52:14 2013 +0200 Add missing copyright header and author information diff --git a/man/vsc2rst.c b/man/vsc2rst.c index d79453b..62b8131 100644 --- a/man/vsc2rst.c +++ b/man/vsc2rst.c @@ -1,4 +1,32 @@ -/* XXX: Copyright ?? */ +/*- + * Copyright (c) 2011-2013 Varnish Software AS + * All rights reserved. + * + * Author: Tollef Fog Heen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + #include "config.h" #include From martin at varnish-cache.org Wed Sep 11 13:05:57 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Wed, 11 Sep 2013 15:05:57 +0200 Subject: [master] 5d50e8b Add copyright and license information to devicedetect.vcl Message-ID: commit 5d50e8b5007729bb13f2680e262470b8ed14a2be Author: Martin Blix Grydeland Date: Wed Sep 11 15:04:07 2013 +0200 Add copyright and license information to devicedetect.vcl diff --git a/etc/devicedetect.vcl b/etc/devicedetect.vcl index e7aecbf..cbb06fd 100644 --- a/etc/devicedetect.vcl +++ b/etc/devicedetect.vcl @@ -1,3 +1,25 @@ +# Copyright (c) 2012-2013 Varnish Software AS +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. # # detectdevice.vcl - regex based device detection for Varnish # http://github.com/varnish/varnish-devicedetect/ From phk at varnish-cache.org Wed Sep 11 13:09:11 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 11 Sep 2013 15:09:11 +0200 Subject: [master] d91c487 moving on: Pass the IMS candidate objcore to VBF and polish its state engine a bit while here. Message-ID: commit d91c487007f587534235104527f7ce1d7a47b522 Author: Poul-Henning Kamp Date: Wed Sep 11 13:08:36 2013 +0000 moving on: Pass the IMS candidate objcore to VBF and polish its state engine a bit while here. diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index c911933..19c12c7 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -544,6 +544,7 @@ struct busyobj { struct http *bereq0; struct http *bereq; struct http *beresp; + struct objcore *ims_objcore; struct objcore *fetch_objcore; struct object *fetch_obj; struct exp exp; @@ -917,7 +918,7 @@ enum vbf_fetch_mode_e { VBF_BACKGROUND = 2, }; void VBF_Fetch(struct worker *wrk, struct req *req, - struct objcore *oc, enum vbf_fetch_mode_e); + struct objcore *oc, struct objcore *oldoc, enum vbf_fetch_mode_e); /* cache_fetch_proc.c */ struct storage *VFP_GetStorage(struct busyobj *, ssize_t sz); diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index acff988..b1219b5 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -119,7 +119,7 @@ vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo) if (bo->req != NULL) vbf_release_req(bo); (void)VFP_Error(bo, "Abandonned in vcl_backend_fetch"); - return (F_STP_ABANDON); + return (F_STP_DONE); } assert (wrk->handling == VCL_RET_FETCH); return (F_STP_FETCHHDR); @@ -222,7 +222,7 @@ vbf_stp_fetchhdr(struct worker *wrk, struct busyobj *bo) // XXX: wrk->handling = VCL_RET_SYNTH; } - return (F_STP_NOTYET); + INCOMPL(); } /*-------------------------------------------------------------------- @@ -358,7 +358,7 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) if (obj == NULL) { (void)VFP_Error(bo, "Could not get storage"); VDI_CloseFd(&bo->vbc); - return (F_STP_ABANDON); + return (F_STP_DONE); } CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC); @@ -429,43 +429,13 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) VBO_setstate(bo, BOS_FINISHED); VSLb(bo->vsl, SLT_Debug, "YYY REF %d %d", bo->refcount, bo->fetch_obj->objcore->refcnt); - VBO_DerefBusyObj(wrk, &bo); // XXX ? return (F_STP_DONE); } -/*-------------------------------------------------------------------- - */ - -static enum fetch_step -vbf_stp_abandon(struct worker *wrk, struct busyobj *bo) -{ - CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); - CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); - - assert(bo->state == BOS_FAILED); - assert(bo->fetch_objcore->flags & OC_F_FAILED); - VBO_DerefBusyObj(wrk, &bo); // XXX ? - return (F_STP_DONE); -} - -/*-------------------------------------------------------------------- - */ - -static enum fetch_step -vbf_stp_notyet(void) -{ - WRONG("Patience, grashopper, patience..."); - NEEDLESS_RETURN(F_STP_NOTYET); -} - -/*-------------------------------------------------------------------- - */ - static enum fetch_step vbf_stp_done(void) { WRONG("Just plain wrong"); - NEEDLESS_RETURN(F_STP_NOTYET); } /*-------------------------------------------------------------------- @@ -512,11 +482,18 @@ vbf_fetch_thread(struct worker *wrk, void *priv) default: WRONG("Illegal fetch_step"); } - if (stp != F_STP_DONE) - VSLb(bo->vsl, SLT_Debug, "%s -> %s", - vbf_step_name(bo->step), vbf_step_name(stp)); + VSLb(bo->vsl, SLT_Debug, "%s -> %s", + vbf_step_name(bo->step), vbf_step_name(stp)); } assert(WRW_IsReleased(wrk)); + + if (bo->state == BOS_FAILED) + assert(bo->fetch_objcore->flags & OC_F_FAILED); + + if (bo->ims_objcore != NULL) + (void)HSH_DerefObjCore(&wrk->stats, &bo->ims_objcore); + + VBO_DerefBusyObj(wrk, &bo); THR_SetBusyobj(NULL); } @@ -525,13 +502,14 @@ vbf_fetch_thread(struct worker *wrk, void *priv) void VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc, - enum vbf_fetch_mode_e mode) + struct objcore *oldoc, enum vbf_fetch_mode_e mode) { struct busyobj *bo; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); + CHECK_OBJ_ORNULL(oldoc, OBJCORE_MAGIC); bo = VBO_GetBusyObj(wrk, req); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); @@ -547,10 +525,14 @@ VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc, bo->vary = req->vary_b; req->vary_b = NULL; - AZ(bo->fetch_objcore); HSH_Ref(oc); bo->fetch_objcore = oc; + if (oldoc != NULL) { + HSH_Ref(oldoc); + bo->ims_objcore = oldoc; + } + AZ(bo->req); bo->req = req; diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index b2e2b72..02e7bcb 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -416,7 +416,7 @@ cnt_lookup(struct worker *wrk, struct req *req) switch (wrk->handling) { case VCL_RET_DELIVER: if (boc != NULL) { - VBF_Fetch(wrk, req, boc, VBF_BACKGROUND); + VBF_Fetch(wrk, req, boc, oc, VBF_BACKGROUND); } else { (void)HTTP1_DiscardReqBody(req);// XXX: handle err } @@ -494,7 +494,7 @@ cnt_miss(struct worker *wrk, struct req *req) switch (wrk->handling) { case VCL_RET_FETCH: wrk->stats.cache_miss++; - VBF_Fetch(wrk, req, req->objcore, VBF_NORMAL); + VBF_Fetch(wrk, req, req->objcore, NULL, VBF_NORMAL); req->req_step = R_STP_FETCH; return (REQ_FSM_MORE); case VCL_RET_ERROR: @@ -553,7 +553,7 @@ cnt_pass(struct worker *wrk, struct req *req) req->acct_req.pass++; req->objcore = HSH_Private(wrk); CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC); - VBF_Fetch(wrk, req, req->objcore, VBF_PASS); + VBF_Fetch(wrk, req, req->objcore, NULL, VBF_PASS); req->req_step = R_STP_FETCH; break; default: diff --git a/include/tbl/steps.h b/include/tbl/steps.h index 886f4ac..b203503 100644 --- a/include/tbl/steps.h +++ b/include/tbl/steps.h @@ -53,8 +53,6 @@ FETCH_STEP(mkbereq, MKBEREQ, (wrk, bo)) FETCH_STEP(startfetch, STARTFETCH, (wrk, bo)) FETCH_STEP(fetchhdr, FETCHHDR, (wrk, bo)) FETCH_STEP(fetch, FETCH, (wrk, bo)) -FETCH_STEP(abandon, ABANDON, (wrk, bo)) -FETCH_STEP(notyet, NOTYET, ()) FETCH_STEP(done, DONE, ()) #endif From martin at varnish-cache.org Wed Sep 11 13:22:56 2013 From: martin at varnish-cache.org (Martin Blix Grydeland) Date: Wed, 11 Sep 2013 15:22:56 +0200 Subject: [master] 07b41c4 Update copyright Message-ID: commit 07b41c41e1d42ef7d40e8639bbceb252fb1b462f Author: Martin Blix Grydeland Date: Wed Sep 11 15:22:30 2013 +0200 Update copyright diff --git a/include/vapi/vsl.h b/include/vapi/vsl.h index 0e434d0..b5d10f8 100644 --- a/include/vapi/vsl.h +++ b/include/vapi/vsl.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS + * Copyright (c) 2006-2013 Varnish Software AS * All rights reserved. * * Author: Poul-Henning Kamp From phk at varnish-cache.org Wed Sep 11 14:44:44 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 11 Sep 2013 16:44:44 +0200 Subject: [master] 48821b4 Add the skeleton of a Conditional Fetch facility. Message-ID: commit 48821b46b0714d23692174240042d38e88a4d69a Author: Poul-Henning Kamp Date: Wed Sep 11 14:40:22 2013 +0000 Add the skeleton of a Conditional Fetch facility. This comes with a big apology to Geoff Simmons: I should have tackled Conditional Fetch before even thinking about streaming and therefore this has taken much longer than it should. diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 19c12c7..f23241c 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -544,9 +544,10 @@ struct busyobj { struct http *bereq0; struct http *bereq; struct http *beresp; - struct objcore *ims_objcore; + struct object *ims_obj; struct objcore *fetch_objcore; struct object *fetch_obj; + struct exp exp; struct http_conn htc; @@ -918,7 +919,7 @@ enum vbf_fetch_mode_e { VBF_BACKGROUND = 2, }; void VBF_Fetch(struct worker *wrk, struct req *req, - struct objcore *oc, struct objcore *oldoc, enum vbf_fetch_mode_e); + struct objcore *oc, struct object *oldobj, enum vbf_fetch_mode_e); /* cache_fetch_proc.c */ struct storage *VFP_GetStorage(struct busyobj *, ssize_t sz); @@ -1127,6 +1128,7 @@ void VRY_Validate(const uint8_t *vary); void VRY_Prep(struct req *); enum vry_finish_flag { KEEP, DISCARD }; void VRY_Finish(struct req *req, enum vry_finish_flag); +unsigned VRY_Len(const uint8_t *); /* cache_vcl.c */ void VCL_Init(void); diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index b1219b5..a49ae95 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -60,6 +60,7 @@ vbf_release_req(struct busyobj *bo) static enum fetch_step vbf_stp_mkbereq(const struct worker *wrk, struct busyobj *bo) { + char *p; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); @@ -86,6 +87,17 @@ vbf_stp_mkbereq(const struct worker *wrk, struct busyobj *bo) http_SetHeader(bo->bereq0, "Accept-Encoding: gzip"); } } + if (bo->ims_obj != NULL) { + if (http_GetHdr(bo->ims_obj->http, H_Last_Modified, &p)) { + http_PrintfHeader(bo->bereq0, + "If-Modified-Since: %s", p); + } else if (http_GetHdr(bo->ims_obj->http, H_ETag, &p)) { + http_PrintfHeader(bo->bereq0, + "If-None-Match: %s", p); + } else { + WRONG("Shouldn't have bo->ims_obj"); + } + } return (F_STP_STARTFETCH); } @@ -131,7 +143,7 @@ vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo) static enum fetch_step vbf_stp_fetchhdr(struct worker *wrk, struct busyobj *bo) { - int i; + int i, do_ims; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); @@ -203,6 +215,14 @@ vbf_stp_fetchhdr(struct worker *wrk, struct busyobj *bo) AZ(bo->do_esi); + if (bo->ims_obj != NULL && bo->beresp->status == 304) { + bo->beresp->status = 200; + http_PrintfHeader(bo->beresp, "Content-Length: %jd", + bo->ims_obj->len); + do_ims = 1; + } else + do_ims = 0; + VCL_backend_response_method(bo->vcl, wrk, NULL, bo, bo->beresp->ws); if (bo->do_esi) @@ -211,7 +231,7 @@ vbf_stp_fetchhdr(struct worker *wrk, struct busyobj *bo) bo->fetch_objcore->flags |= OC_F_PASS; if (wrk->handling == VCL_RET_DELIVER) - return (F_STP_FETCH); + return (do_ims ? F_STP_CONDFETCH : F_STP_FETCH); if (wrk->handling == VCL_RET_RETRY) { assert(bo->state == BOS_REQ_DONE); bo->retries++; @@ -239,7 +259,6 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo) int varyl = 0; struct object *obj; - CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); @@ -441,6 +460,99 @@ vbf_stp_done(void) /*-------------------------------------------------------------------- */ +static enum fetch_step +vbf_stp_condfetch(struct worker *wrk, struct busyobj *bo) +{ + unsigned l; + uint16_t nhttp; + struct object *obj; + struct objiter *oi; + void *sp; + ssize_t sl, al, tl; + struct storage *st; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); + + l = 0; + if (bo->ims_obj->vary != NULL) + l += VRY_Len(bo->ims_obj->vary); + l += http_EstimateWS(bo->ims_obj->http, 0, &nhttp); + + bo->stats = &wrk->stats; + obj = STV_NewObject(bo, bo->storage_hint, l, nhttp); + if (obj == NULL) { + (void)VFP_Error(bo, "Could not get storage"); + VDI_CloseFd(&bo->vbc); + return (F_STP_DONE); + } + bo->stats = NULL; + + AZ(bo->fetch_obj); + bo->fetch_obj = obj; + + obj->gziped = bo->ims_obj->gziped; + obj->gzip_start = bo->ims_obj->gzip_start; + obj->gzip_last = bo->ims_obj->gzip_last; + obj->gzip_stop = bo->ims_obj->gzip_stop; + + /* XXX: ESI */ + + if (bo->ims_obj->vary != NULL) + obj->vary = (void *)WS_Copy(obj->http->ws, + bo->ims_obj->vary, VRY_Len(bo->ims_obj->vary)); + + obj->vxid = bo->vsl->wid; + + obj->http->logtag = HTTP_Obj; + /* XXX: we should have our own HTTP_A_CONDFETCH */ + http_FilterResp(bo->ims_obj->http, obj->http, HTTPH_A_INS); + http_CopyHome(obj->http); + + + if (!(bo->fetch_obj->objcore->flags & OC_F_PRIVATE)) { + EXP_Insert(obj); + AN(obj->objcore->ban); + } + + AZ(bo->ws_o->overflow); + VBO_setstate(bo, BOS_FETCHING); + HSH_Unbusy(&wrk->stats, obj->objcore); + + st = NULL; + al = 0; + + oi = ObjIterBegin(wrk, bo->ims_obj); + while (1 == ObjIter(oi, &sp, &sl)) { + while (sl > 0) { + if (st == NULL) { + st = VFP_GetStorage(bo, bo->ims_obj->len - al); + XXXAN(st); + } + tl = sl; + if (tl > st->space - st->len) + tl = st->space - st->len; + memcpy(st->ptr + st->len, sp, tl); + st->len += tl; + al += tl; + sp = (char *)sp + tl; + sl -= tl; + VBO_extend(bo, al); + if (st->len == st->space) + st = NULL; + } + } + assert(al == bo->ims_obj->len); + assert(obj->len == al); + if (bo->state != BOS_FAILED) + VBO_setstate(bo, BOS_FINISHED); + HSH_Complete(obj->objcore); + return (F_STP_DONE); +} + +/*-------------------------------------------------------------------- + */ + static const char * vbf_step_name(enum fetch_step stp) { @@ -490,8 +602,8 @@ vbf_fetch_thread(struct worker *wrk, void *priv) if (bo->state == BOS_FAILED) assert(bo->fetch_objcore->flags & OC_F_FAILED); - if (bo->ims_objcore != NULL) - (void)HSH_DerefObjCore(&wrk->stats, &bo->ims_objcore); + if (bo->ims_obj != NULL) + (void)HSH_DerefObj(&wrk->stats, &bo->ims_obj); VBO_DerefBusyObj(wrk, &bo); THR_SetBusyobj(NULL); @@ -502,14 +614,14 @@ vbf_fetch_thread(struct worker *wrk, void *priv) void VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc, - struct objcore *oldoc, enum vbf_fetch_mode_e mode) + struct object *oldobj, enum vbf_fetch_mode_e mode) { struct busyobj *bo; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); - CHECK_OBJ_ORNULL(oldoc, OBJCORE_MAGIC); + CHECK_OBJ_ORNULL(oldobj, OBJECT_MAGIC); bo = VBO_GetBusyObj(wrk, req); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); @@ -528,9 +640,12 @@ VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc, HSH_Ref(oc); bo->fetch_objcore = oc; - if (oldoc != NULL) { - HSH_Ref(oldoc); - bo->ims_objcore = oldoc; + if (oldobj != NULL) { + if (http_GetHdr(oldobj->http, H_Last_Modified, NULL) || + http_GetHdr(oldobj->http, H_ETag, NULL)) { + HSH_Ref(oldobj->objcore); + bo->ims_obj = oldobj; + } } AZ(bo->req); diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 02e7bcb..b0e7be7 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -416,7 +416,7 @@ cnt_lookup(struct worker *wrk, struct req *req) switch (wrk->handling) { case VCL_RET_DELIVER: if (boc != NULL) { - VBF_Fetch(wrk, req, boc, oc, VBF_BACKGROUND); + VBF_Fetch(wrk, req, boc, o, VBF_BACKGROUND); } else { (void)HTTP1_DiscardReqBody(req);// XXX: handle err } diff --git a/bin/varnishd/cache/cache_vary.c b/bin/varnishd/cache/cache_vary.c index 9dddf60..363e357 100644 --- a/bin/varnishd/cache/cache_vary.c +++ b/bin/varnishd/cache/cache_vary.c @@ -173,8 +173,8 @@ VRY_Create(struct busyobj *bo, struct vsb **psb) /* * Find length of a vary entry */ -static unsigned -vry_len(const uint8_t *p) +unsigned +VRY_Len(const uint8_t *p) { unsigned l = vbe16dec(p); @@ -189,7 +189,7 @@ vry_cmp(const uint8_t *v1, const uint8_t *v2) { unsigned retval = 0; - if (!memcmp(v1, v2, vry_len(v1))) { + if (!memcmp(v1, v2, VRY_Len(v1))) { /* Same same */ retval = 0; } else if (memcmp(v1 + 2, v2 + 2, v1[2] + 2)) { @@ -331,8 +331,8 @@ VRY_Match(struct req *req, const uint8_t *vary) } if (i == 0) { /* Same header, same contents*/ - vsp += vry_len(vsp); - vary += vry_len(vary); + vsp += VRY_Len(vsp); + vary += VRY_Len(vary); } else if (i == 2) { /* Same header, different contents, cannot match */ return (0); @@ -358,6 +358,6 @@ VRY_Validate(const uint8_t *vary) while (vary[2] != 0) { assert(strlen((const char*)vary+3) == vary[2]); - vary += vry_len(vary); + vary += VRY_Len(vary); } } diff --git a/include/tbl/steps.h b/include/tbl/steps.h index b203503..e18b7f3 100644 --- a/include/tbl/steps.h +++ b/include/tbl/steps.h @@ -52,6 +52,7 @@ REQ_STEP(error, ERROR, (wrk, req)) FETCH_STEP(mkbereq, MKBEREQ, (wrk, bo)) FETCH_STEP(startfetch, STARTFETCH, (wrk, bo)) FETCH_STEP(fetchhdr, FETCHHDR, (wrk, bo)) +FETCH_STEP(condfetch, CONDFETCH, (wrk, bo)) FETCH_STEP(fetch, FETCH, (wrk, bo)) FETCH_STEP(done, DONE, ()) #endif From phk at varnish-cache.org Wed Sep 11 14:45:40 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 11 Sep 2013 16:45:40 +0200 Subject: [master] 53e6f23 Trivial test-case for conditional fetch Message-ID: commit 53e6f23a285c5e4b31af0f982a6b4aa90ed2e98a Author: Poul-Henning Kamp Date: Wed Sep 11 14:45:27 2013 +0000 Trivial test-case for conditional fetch diff --git a/bin/varnishtest/tests/b00039.vtc b/bin/varnishtest/tests/b00039.vtc new file mode 100644 index 0000000..cf1e9dc --- /dev/null +++ b/bin/varnishtest/tests/b00039.vtc @@ -0,0 +1,40 @@ +varnishtest "Test IMS" + +server s1 { + rxreq + txresp -hdr "Last-Modified: Wed, 11 Sep 2013 13:36:55 GMT" -body "Geoff Rules" + rxreq + expect req.http.if-modified-since == "Wed, 11 Sep 2013 13:36:55 GMT" + txresp -status 304 +} -start + +varnish v1 -vcl+backend { + sub vcl_backend_response { + set beresp.ttl = 2s; + set beresp.grace = 20s; + set beresp.keep = 1m; + } +} -start + +client c1 { + txreq + rxresp + expect resp.status == 200 + expect resp.body == "Geoff Rules" +} -run + +delay 3 + +client c1 { + txreq + rxresp + expect resp.status == 200 + expect resp.body == "Geoff Rules" +} -run + +client c1 { + txreq + rxresp + expect resp.status == 200 + expect resp.body == "Geoff Rules" +} -run From apj at varnish-cache.org Thu Sep 12 17:29:28 2013 From: apj at varnish-cache.org (Andreas Plesner Jacobsen) Date: Thu, 12 Sep 2013 19:29:28 +0200 Subject: [master] 09548e6 Fix links, update RedHat section, small language and content nits Message-ID: commit 09548e6a04044235971c04e1ab8ffdb48ddd4872 Author: Andreas Plesner Jacobsen Date: Thu Sep 12 19:28:19 2013 +0200 Fix links, update RedHat section, small language and content nits diff --git a/doc/sphinx/installation/install.rst b/doc/sphinx/installation/install.rst index cf7501f..e0b0ceb 100644 --- a/doc/sphinx/installation/install.rst +++ b/doc/sphinx/installation/install.rst @@ -6,7 +6,7 @@ Installing Varnish With open source software, you can choose to install binary packages or compile stuff from source-code. To install a package or compile from source is a matter of personal taste. If you don't know which -method too choose read the whole document and choose the method you +method to choose, read the whole document and choose the method you are most comfortable with. @@ -20,26 +20,24 @@ being: FreeBSD ------- -From source: - ``cd /usr/ports/varnish && make install clean`` Binary package: ``pkg_add -r varnish`` +From source: + ``cd /usr/ports/varnish && make install clean`` CentOS/RedHat ------------- -We try to keep the latest version available as prebuilt RPMs (el5) on -`repo.varnish-cache.org `. See the +We try to keep the latest version available as prebuilt RPMs (el5 and el6) +on `repo.varnish-cache.org `. See the `RedHat installation instructions -` for more information. +`_ for more information. Varnish is included in the `EPEL -`_ repository. Unfortunately we -had a syntax change in Varnish 2.0.6->2.1.X. This means that we can -not update Varnish in `EPEL 5 `_ so -the latest version there is Varnish 2.0.6. - -EPEL6 should have Varnish 2.1 available once it releases. +`_ repository, however due to +incompatible syntax changes in newer versions of Varnish, only older +versions are available. We recommend that you install the latest +version from our repository. Debian/Ubuntu ------------- @@ -49,18 +47,8 @@ Varnish up and running type `sudo apt-get install varnish`. Please note that this might not be the latest version of Varnish. If you need a later version of Varnish, please follow the installation instructions for `Debian -` or `Ubuntu -`. - -Other systems -------------- - -You are probably best of compiling your own code. See `Compiling -Varnish from source`_. - -If that worked for you, you can skip the rest of this document for -now, and and start reading the much more interesting -:ref:`tutorial-index` instead. +`_ or `Ubuntu +`_. Compiling Varnish from source @@ -71,7 +59,7 @@ want to compile Varnish from source for other reasons, follow these steps: We recommend downloading a release tarball, which you can find on -`repo.varnish-cache.org `. +`repo.varnish-cache.org `_. Alternatively, if you want to hack on Varnish, you should clone our git repository by doing. @@ -125,12 +113,12 @@ The ``configure`` script takes some arguments, but more likely than not, you can forget about that for now, almost everything in Varnish are run time parameters. -Before you install, you may want to run the regression tests, make -a cup of tea while it runs, it takes some minutes:: +Before you install, you may want to run the test suite, make a cup of +tea while it runs, it takes some minutes:: make check -Don't worry of a single or two tests fail, some of the tests are a +Don't worry if a single or two tests fail, some of the tests are a bit too timing sensitive (Please tell us which so we can fix it) but if a lot of them fails, and in particular if the ``b00000.vtc`` test fails, something is horribly wrong, and you will get nowhere without From tfheen at varnish-cache.org Fri Sep 13 11:31:00 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Fri, 13 Sep 2013 13:31:00 +0200 Subject: [master] cfd5281 Fix up order of arguments in error message Message-ID: commit cfd52815c5e7af449cc9bf7e16230eae4ad77a8e Author: Tollef Fog Heen Date: Fri Sep 13 13:30:42 2013 +0200 Fix up order of arguments in error message diff --git a/bin/varnishd/storage/stevedore_utils.c b/bin/varnishd/storage/stevedore_utils.c index 2364289..4b0b09a 100644 --- a/bin/varnishd/storage/stevedore_utils.c +++ b/bin/varnishd/storage/stevedore_utils.c @@ -201,7 +201,7 @@ STV_FileSize(int fd, const char *size, unsigned *granularity, const char *ctx) q = VNUM_2bytes(size, &l, fssize); if (q != NULL) - ARGV_ERR("(%s) size \"%s\": %s\n", size, ctx, q); + ARGV_ERR("(%s) size \"%s\": %s\n", ctx, size, q); if (l < 1024*1024) ARGV_ERR("(-spersistent) size \"%s\": too small, " From tfheen at varnish-cache.org Fri Sep 13 11:31:00 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Fri, 13 Sep 2013 13:31:00 +0200 Subject: [master] 375ee2d Use ctx rather than hard coding -spersistent Message-ID: commit 375ee2da941d15fb65df4bf9a8c0f62e46e71cd6 Author: Tollef Fog Heen Date: Fri Sep 13 13:30:56 2013 +0200 Use ctx rather than hard coding -spersistent diff --git a/bin/varnishd/storage/stevedore_utils.c b/bin/varnishd/storage/stevedore_utils.c index 4b0b09a..92f531b 100644 --- a/bin/varnishd/storage/stevedore_utils.c +++ b/bin/varnishd/storage/stevedore_utils.c @@ -204,8 +204,8 @@ STV_FileSize(int fd, const char *size, unsigned *granularity, const char *ctx) ARGV_ERR("(%s) size \"%s\": %s\n", ctx, size, q); if (l < 1024*1024) - ARGV_ERR("(-spersistent) size \"%s\": too small, " - "did you forget to specify M or G?\n", size); + ARGV_ERR("(%s) size \"%s\": too small, " + "did you forget to specify M or G?\n", ctx, size); } /* From lkarsten at varnish-cache.org Fri Sep 13 14:44:33 2013 From: lkarsten at varnish-cache.org (Lasse Karstensen) Date: Fri, 13 Sep 2013 16:44:33 +0200 Subject: [master] 668cee8 Lint: Add whitespace for readability Message-ID: commit 668cee81262ac12b799a53551ace933286968abb Author: Lasse Karstensen Date: Fri Sep 13 16:44:26 2013 +0200 Lint: Add whitespace for readability diff --git a/bin/varnishd/mgt/mgt_param_tbl.c b/bin/varnishd/mgt/mgt_param_tbl.c index 65a70b5..d4fcb53 100644 --- a/bin/varnishd/mgt/mgt_param_tbl.c +++ b/bin/varnishd/mgt/mgt_param_tbl.c @@ -586,9 +586,9 @@ const struct parspec mgt_parspec[] = { { "busyobj_worker_cache", tweak_bool, &mgt_param.bo_cache, 0, 0, - "Cache free busyobj per worker thread." - "Disable this if you have very high hitrates and want" - "to save the memory of one busyobj per worker thread.", + "Cache free busyobj per worker thread. " + "Disable this if you have very high hitrates and want " + "to save the memory of one busyobj per worker thread. ", 0, "off", "bool"}, From phk at varnish-cache.org Mon Sep 16 09:14:31 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 16 Sep 2013 11:14:31 +0200 Subject: [master] 2c16067 Clear the req->wrk while holding the oh mutex, to close a race against the busy-list. Message-ID: commit 2c1606779d86b5afee891465031f4f159b3e29d6 Author: Poul-Henning Kamp Date: Mon Sep 16 09:13:39 2013 +0000 Clear the req->wrk while holding the oh mutex, to close a race against the busy-list. Fixes #1342 diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c index b653d50..e2959fe 100644 --- a/bin/varnishd/cache/cache_hash.c +++ b/bin/varnishd/cache/cache_hash.c @@ -494,13 +494,14 @@ HSH_Lookup(struct req *req, struct objcore **ocp, struct objcore **bocp, req, w_list); if (DO_DEBUG(DBG_WAITINGLIST)) VSLb(req->vsl, SLT_Debug, "on waiting list <%p>", oh); + req->wrk = NULL; } else { if (DO_DEBUG(DBG_WAITINGLIST)) VSLb(req->vsl, SLT_Debug, "hit busy obj <%p>", oh); } wrk->stats.busy_sleep++; - SES_Charge(req->wrk, req); + SES_Charge(wrk, req); /* * The objhead reference transfers to the sess, we get it * back when the sess comes off the waiting list and From phk at varnish-cache.org Mon Sep 16 09:26:05 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 16 Sep 2013 11:26:05 +0200 Subject: [master] 80ee073 Take a stab at #1341 Message-ID: commit 80ee0738ac7441d09a2e822a24bef87c24b9e8ea Author: Poul-Henning Kamp Date: Mon Sep 16 09:25:46 2013 +0000 Take a stab at #1341 diff --git a/bin/varnishd/cache/cache_busyobj.c b/bin/varnishd/cache/cache_busyobj.c index ca721b7..8f49b20 100644 --- a/bin/varnishd/cache/cache_busyobj.c +++ b/bin/varnishd/cache/cache_busyobj.c @@ -228,7 +228,8 @@ ssize_t VBO_waitlen(struct busyobj *bo, ssize_t l) { Lck_Lock(&bo->mtx); - assert(l <= bo->fetch_obj->len); + if (bo->state <= BOS_FINISHED) + assert(l <= bo->fetch_obj->len); while (1) { if (bo->fetch_obj->len > l || bo->state >= BOS_FINISHED) { l = bo->fetch_obj->len; From phk at varnish-cache.org Mon Sep 16 10:19:28 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 16 Sep 2013 12:19:28 +0200 Subject: [master] 69ad738 By default ignore an with src="https://..." Message-ID: commit 69ad7389fe3aee4481aa4f291461bc03e1bc172a Author: Poul-Henning Kamp Date: Mon Sep 16 10:18:22 2013 +0000 By default ignore an with src="https://..." Feature +esi_ignore_https treats it as http://... instead. Default is "safe" in order to not expose any data by accident. Fixes #1333 diff --git a/bin/varnishd/cache/cache_esi_parse.c b/bin/varnishd/cache/cache_esi_parse.c index 1b043a3..68c96e6 100644 --- a/bin/varnishd/cache/cache_esi_parse.c +++ b/bin/varnishd/cache/cache_esi_parse.c @@ -457,7 +457,6 @@ vep_do_include(struct vep_state *vep, enum dowhat what) vep->include_src = NULL; return; } - XXXAZ(vep->include_src); /* multiple src= */ vep->include_src = vep->attr_vsb; return; } @@ -486,17 +485,34 @@ vep_do_include(struct vep_state *vep, enum dowhat what) l = VSB_len(vep->include_src); h = 0; - VSB_printf(vep->vsb, "%c", VEC_INCL); if (l > 7 && !memcmp(p, "http://", 7)) { h = p + 7; p = strchr(h, '/'); AN(p); Debug("HOST <%.*s> PATH <%s>\n", (int)(p-h),h, p); - VSB_printf(vep->vsb, "Host: %.*s%c", - (int)(p-h), h, 0); + VSB_printf(vep->vsb, "%c", VEC_INCL); + VSB_printf(vep->vsb, "Host: %.*s%c", (int)(p-h), h, 0); + } else if (l > 8 && !memcmp(p, "https://", 8)) { + if (!FEATURE(FEATURE_ESI_IGNORE_HTTPS)) { + vep_warn(vep, + "ESI 1.0 with https:// ignored"); + vep->state = VEP_TAGERROR; + vep->attr_vsb = NULL; + vep->include_src = NULL; + return; + } + vep_warn(vep, + "ESI 1.0 https:// treated as http://"); + h = p + 8; + p = strchr(h, '/'); + AN(p); + VSB_printf(vep->vsb, "%c", VEC_INCL); + VSB_printf(vep->vsb, "Host: %.*s%c", (int)(p-h), h, 0); } else if (*p == '/') { + VSB_printf(vep->vsb, "%c", VEC_INCL); VSB_printf(vep->vsb, "%c", 0); } else { + VSB_printf(vep->vsb, "%c", VEC_INCL); VSB_printf(vep->vsb, "%c", 0); url = vep->bo->bereq->hd[HTTP_HDR_URL]; /* Look for the last / before a '?' */ diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index a49ae95..cb59bad 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -220,7 +220,7 @@ vbf_stp_fetchhdr(struct worker *wrk, struct busyobj *bo) http_PrintfHeader(bo->beresp, "Content-Length: %jd", bo->ims_obj->len); do_ims = 1; - } else + } else do_ims = 0; VCL_backend_response_method(bo->vcl, wrk, NULL, bo, bo->beresp->ws); diff --git a/bin/varnishtest/tests/r01333.vtc b/bin/varnishtest/tests/r01333.vtc new file mode 100644 index 0000000..7b712e0 --- /dev/null +++ b/bin/varnishtest/tests/r01333.vtc @@ -0,0 +1,46 @@ +varnishtest "ESI:include with https" + +server s1 { + rxreq + expect req.url == "/" + txresp -body { + + Before include + + After include + } + + rxreq + expect req.url == "/foo" + txresp -body { + + Before include + + After include + } + rxreq + expect req.url == "/body" + expect req.http.host == "bozz" + txresp -body BAR + +} -start + +varnish v1 -vcl+backend { + sub vcl_backend_response { + set beresp.do_esi = true; + } +} -start + +client c1 { + txreq + rxresp + expect resp.bodylen == 49 +} -run + +varnish v1 -cliok "param.set feature +esi_ignore_https" + +client c1 { + txreq -url /foo + rxresp + expect resp.bodylen == 52 +} -run diff --git a/include/tbl/feature_bits.h b/include/tbl/feature_bits.h index 9d99449..e6970ad 100644 --- a/include/tbl/feature_bits.h +++ b/include/tbl/feature_bits.h @@ -41,3 +41,7 @@ FEATURE_BIT(NO_COREDUMP, no_coredump, "", "No coredumps.", "Don't attempt to coredump child process on panics." ) +FEATURE_BIT(ESI_IGNORE_HTTPS, esi_ignore_https, "", + "Treat HTTPS as HTTP in ESI:includes", + "Convert commit fe1f9b11a0574bb569885c10fe28ebffaa8983a9 Author: Poul-Henning Kamp Date: Tue Sep 17 07:40:10 2013 +0000 Retire the "esi_syntax" bitmap parameter, and turn the still remaining bits into "feature" and "debug" flags. diff --git a/bin/varnishd/cache/cache_esi_fetch.c b/bin/varnishd/cache/cache_esi_fetch.c index e64d796..c3274b1 100644 --- a/bin/varnishd/cache/cache_esi_fetch.c +++ b/bin/varnishd/cache/cache_esi_fetch.c @@ -59,7 +59,7 @@ struct vef_priv { /*--------------------------------------------------------------------- * Read some bytes. * - * If the esi_syntax&8 bit is set, we read only a couple of bytes at + * If the DBG_ESI_CHOP is set, we read only a couple of bytes at * a time, in order to stress the parse/pending/callback code. */ @@ -70,7 +70,7 @@ vef_read(struct http_conn *htc, void *buf, ssize_t buflen, ssize_t bytes) if (buflen < bytes) bytes = buflen; - if (cache_param->esi_syntax & 0x8) { + if (DO_DEBUG(DBG_ESI_CHOP)) { d = (random() & 3) + 1; if (d < bytes) bytes = d; diff --git a/bin/varnishd/cache/cache_esi_parse.c b/bin/varnishd/cache/cache_esi_parse.c index 68c96e6..e173b93 100644 --- a/bin/varnishd/cache/cache_esi_parse.c +++ b/bin/varnishd/cache/cache_esi_parse.c @@ -268,9 +268,6 @@ static void vep_emit_skip(const struct vep_state *vep, ssize_t l) { - if (cache_param->esi_syntax & 0x20) { - Debug("---> SKIP(%jd)\n", (intmax_t)l); - } vep_emit_len(vep, l, VEC_S1, VEC_S2, VEC_S8); } @@ -279,9 +276,6 @@ vep_emit_verbatim(const struct vep_state *vep, ssize_t l, ssize_t l_crc) { uint8_t buf[4]; - if (cache_param->esi_syntax & 0x20) { - Debug("---> VERBATIM(%jd)\n", (intmax_t)l); - } vep_emit_len(vep, l, VEC_V1, VEC_V2, VEC_V8); if (vep->dogzip) { vep_emit_len(vep, l_crc, VEC_C1, VEC_C2, VEC_C8); @@ -600,7 +594,7 @@ VEP_Parse(const struct busyobj *bo, const char *p, size_t l) */ if (vep->state == VEP_START) { - if (cache_param->esi_syntax & 0x1) + if (FEATURE(FEATURE_ESI_DISABLE_XML_CHECK)) vep->state = VEP_NEXTTAG; else vep->state = VEP_TESTXML; @@ -633,7 +627,7 @@ VEP_Parse(const struct busyobj *bo, const char *p, size_t l) */ } else if (vep->state == VEP_NOTMYTAG) { - if (cache_param->esi_syntax & 0x2) { + if (FEATURE(FEATURE_ESI_IGNORE_OTHER_ELEMENTS)) { p++; vep->state = VEP_NEXTTAG; } else { diff --git a/bin/varnishd/mgt/mgt_param_tbl.c b/bin/varnishd/mgt/mgt_param_tbl.c index d4fcb53..6a0fc7c 100644 --- a/bin/varnishd/mgt/mgt_param_tbl.c +++ b/bin/varnishd/mgt/mgt_param_tbl.c @@ -323,17 +323,6 @@ const struct parspec mgt_parspec[] = { "Upper limit on how many times a backend fetch can retry.\n", 0, "4", "retries" }, - { "esi_syntax", - tweak_uint, &mgt_param.esi_syntax, 0, UINT_MAX, - "Bitmap controlling ESI parsing code:\n" - " 0x00000001 - Don't check if it looks like XML\n" - " 0x00000002 - Ignore non-esi elements\n" - " 0x00000004 - Emit parsing debug records\n" - " 0x00000008 - Force-split parser input (debugging)\n" - "\n" - "Use 0x notation and do the bitor in your head :-)\n", - 0, - "0", "bitmap" }, { "max_esi_depth", tweak_uint, &mgt_param.max_esi_depth, 0, UINT_MAX, "Maximum depth of esi:include processing.\n", diff --git a/bin/varnishtest/tests/e00001.vtc b/bin/varnishtest/tests/e00001.vtc index e988fb5..42a0c24 100644 --- a/bin/varnishtest/tests/e00001.vtc +++ b/bin/varnishtest/tests/e00001.vtc @@ -17,7 +17,7 @@ varnish v1 -vcl+backend { sub vcl_backend_response { set beresp.do_esi = true; } -} -start -cliok "param.set esi_syntax 4" +} -start client c1 { txreq diff --git a/bin/varnishtest/tests/e00008.vtc b/bin/varnishtest/tests/e00008.vtc index 53545d6..e99dac9 100644 --- a/bin/varnishtest/tests/e00008.vtc +++ b/bin/varnishtest/tests/e00008.vtc @@ -61,7 +61,7 @@ varnish v1 -vcl+backend { } } -start -varnish v1 -cliok "param.set esi_syntax 0x3e" +varnish v1 -cliok "param.set debug +esi_chop" varnish v1 -cliok "param.set debug +syncvsl" diff --git a/bin/varnishtest/tests/e00009.vtc b/bin/varnishtest/tests/e00009.vtc index e2ef6b3..938c200 100644 --- a/bin/varnishtest/tests/e00009.vtc +++ b/bin/varnishtest/tests/e00009.vtc @@ -30,7 +30,7 @@ client c1 { expect resp.bodylen == 57 } -run -varnish v1 -cli "param.set esi_syntax 1" +varnish v1 -cli "param.set feature +esi_disable_xml_check" client c1 { txreq -url bar diff --git a/bin/varnishtest/tests/e00010.vtc b/bin/varnishtest/tests/e00010.vtc index 513a99a..0fccc41 100644 --- a/bin/varnishtest/tests/e00010.vtc +++ b/bin/varnishtest/tests/e00010.vtc @@ -15,7 +15,7 @@ varnish v1 -vcl+backend { sub vcl_backend_response { set beresp.do_esi = true; } -} -start -cli "param.set esi_syntax 2" +} -start -cli "param.set feature +esi_ignore_other_elements" client c1 { txreq diff --git a/bin/varnishtest/tests/e00019.vtc b/bin/varnishtest/tests/e00019.vtc index 6a4b402..374bb18 100644 --- a/bin/varnishtest/tests/e00019.vtc +++ b/bin/varnishtest/tests/e00019.vtc @@ -36,8 +36,7 @@ varnish v1 -vcl+backend { } } -start -varnish v1 -cliok "param.set esi_syntax 8" - +varnish v1 -cliok "param.set debug +esi_chop" varnish v1 -cliok "param.set debug +syncvsl" client c1 { diff --git a/bin/varnishtest/tests/e00020.vtc b/bin/varnishtest/tests/e00020.vtc index 55d6923..121c80e 100644 --- a/bin/varnishtest/tests/e00020.vtc +++ b/bin/varnishtest/tests/e00020.vtc @@ -20,7 +20,6 @@ varnish v1 -vcl+backend { } } -start -varnish v1 -cliok "param.set esi_syntax 4" varnish v1 -cliok "param.set http_gzip_support true" client c1 { diff --git a/bin/varnishtest/tests/e00021.vtc b/bin/varnishtest/tests/e00021.vtc index 26acd2c..9a0ead2 100644 --- a/bin/varnishtest/tests/e00021.vtc +++ b/bin/varnishtest/tests/e00021.vtc @@ -23,7 +23,7 @@ varnish v1 -vcl+backend { } } -start -varnish v1 -cliok "param.set esi_syntax 0xc" +varnish v1 -cliok "param.set debug +esi_chop" varnish v1 -cliok "param.set http_gzip_support true" client c1 { diff --git a/bin/varnishtest/tests/e00022.vtc b/bin/varnishtest/tests/e00022.vtc index be980c5..bc5b259 100644 --- a/bin/varnishtest/tests/e00022.vtc +++ b/bin/varnishtest/tests/e00022.vtc @@ -23,7 +23,7 @@ varnish v1 -arg "-p thread_pool_stack=262144" -vcl+backend { } } -start -varnish v1 -cliok "param.set esi_syntax 0xc" +varnish v1 -cliok "param.set debug +esi_chop" varnish v1 -cliok "param.set http_gzip_support true" varnish v1 -cliok "param.set gzip_memlevel 1" diff --git a/bin/varnishtest/tests/e00023.vtc b/bin/varnishtest/tests/e00023.vtc index 2508c9c..893fdf9 100644 --- a/bin/varnishtest/tests/e00023.vtc +++ b/bin/varnishtest/tests/e00023.vtc @@ -42,7 +42,8 @@ varnish v1 -vcl+backend { } -start varnish v1 -cliok "param.set http_gzip_support true" -varnish v1 -cliok "param.set esi_syntax 0x3e" +varnish v1 -cliok "param.set debug +esi_chop" +varnish v1 -cliok "param.set feature +esi_disable_xml_check" varnish v1 -cliok "param.set debug +syncvsl" diff --git a/bin/varnishtest/tests/e00024.vtc b/bin/varnishtest/tests/e00024.vtc index 98b40cd..2ae231e 100644 --- a/bin/varnishtest/tests/e00024.vtc +++ b/bin/varnishtest/tests/e00024.vtc @@ -68,7 +68,7 @@ varnish v1 -vcl+backend { } -start varnish v1 -cliok "param.set http_gzip_support true" -varnish v1 -cliok "param.set esi_syntax 0x3e" +varnish v1 -cliok "param.set debug +esi_chop" varnish v1 -cliok "param.set debug +syncvsl" client c1 { diff --git a/bin/varnishtest/tests/e00026.vtc b/bin/varnishtest/tests/e00026.vtc index d4c3a39..22e04fc 100644 --- a/bin/varnishtest/tests/e00026.vtc +++ b/bin/varnishtest/tests/e00026.vtc @@ -35,7 +35,7 @@ varnish v1 -vcl+backend { } } -start -varnish v1 -cliok "param.set esi_syntax 0x21" +varnish v1 -cliok "param.set feature +esi_disable_xml_check" varnish v1 -cliok "param.set debug +syncvsl" diff --git a/bin/varnishtest/tests/r00433.vtc b/bin/varnishtest/tests/r00433.vtc index 2ccbd3f..01462d4 100644 --- a/bin/varnishtest/tests/r00433.vtc +++ b/bin/varnishtest/tests/r00433.vtc @@ -36,7 +36,6 @@ varnish v1 -vcl+backend { } } -start -varnish v1 -cliok "param.set esi_syntax 4" varnish v1 -cliok "param.set debug +syncvsl" varnish v1 -cliok "debug.fragfetch 32" diff --git a/bin/varnishtest/tests/r01092.vtc b/bin/varnishtest/tests/r01092.vtc index 59aacf3..7248e49 100644 --- a/bin/varnishtest/tests/r01092.vtc +++ b/bin/varnishtest/tests/r01092.vtc @@ -22,7 +22,7 @@ varnish v1 -vcl+backend { sub vcl_backend_response { set beresp.do_esi = true; } -} -start -cliok "param.set esi_syntax 4" +} -start client c1 { txreq diff --git a/include/tbl/debug_bits.h b/include/tbl/debug_bits.h index 72d298d..7c6a655 100644 --- a/include/tbl/debug_bits.h +++ b/include/tbl/debug_bits.h @@ -37,3 +37,4 @@ DEBUG_BIT(SYNCVSL, syncvsl, "\t","Make VSL synchronous") DEBUG_BIT(HASHEDGE, hashedge, "", "Edge cases in Hash") DEBUG_BIT(VCLREL, vclrel, "\t","Rapid VCL release") DEBUG_BIT(LURKER, lurker, "\t","VSL Ban lurker") +DEBUG_BIT(ESI_CHOP, esi_chop, "", "Chop ESI fetch to bits") diff --git a/include/tbl/feature_bits.h b/include/tbl/feature_bits.h index e6970ad..3e4ecba 100644 --- a/include/tbl/feature_bits.h +++ b/include/tbl/feature_bits.h @@ -29,19 +29,27 @@ * */ -FEATURE_BIT(SHORT_PANIC, short_panic, "", +FEATURE_BIT(SHORT_PANIC, short_panic, "", "Short panic message.", "Reduce level of detail for panic messages." ) -FEATURE_BIT(WAIT_SILO, wait_silo, "", +FEATURE_BIT(WAIT_SILO, wait_silo, "", "Wait for persistent silo.", "Wait for persistent silos to load completely before serving requests." ) -FEATURE_BIT(NO_COREDUMP, no_coredump, "", +FEATURE_BIT(NO_COREDUMP, no_coredump, "", "No coredumps.", "Don't attempt to coredump child process on panics." ) -FEATURE_BIT(ESI_IGNORE_HTTPS, esi_ignore_https, "", +FEATURE_BIT(ESI_IGNORE_HTTPS, esi_ignore_https, "", "Treat HTTPS as HTTP in ESI:includes", "Convert , >=, < & <=) Message-ID: commit 35561bcb27541d0e1ee4fae76c7c3e3bc5f1697d Author: Poul-Henning Kamp Date: Tue Sep 17 09:09:54 2013 +0000 Implement relational expects (>, >=, < & <=) You have to be careful when you use them though: They compare strings. diff --git a/bin/varnishtest/vtc_http.c b/bin/varnishtest/vtc_http.c index cf51baf..3ac966b 100644 --- a/bin/varnishtest/vtc_http.c +++ b/bin/varnishtest/vtc_http.c @@ -220,7 +220,7 @@ cmd_http_expect(CMD_ARGS) vre_t *vre; const char *error; int erroroffset; - int i; + int i, retval = -1; (void)cmd; (void)vl; @@ -236,37 +236,33 @@ cmd_http_expect(CMD_ARGS) cmp = av[1]; rhs = cmd_var_resolve(hp, av[2]); if (!strcmp(cmp, "==")) { - if (strcmp(lhs, rhs)) - vtc_log(hp->vl, 0, "EXPECT %s (%s) %s %s (%s) failed", - av[0], lhs, av[1], av[2], rhs); - else - vtc_log(hp->vl, 4, "EXPECT %s (%s) %s %s (%s) match", - av[0], lhs, av[1], av[2], rhs); + retval = strcmp(lhs, rhs) == 0; + } else if (!strcmp(cmp, "<")) { + retval = strcmp(lhs, rhs) < 0; + } else if (!strcmp(cmp, "<=")) { + retval = strcmp(lhs, rhs) <= 0; + } else if (!strcmp(cmp, ">=")) { + retval = strcmp(lhs, rhs) >= 0; + } else if (!strcmp(cmp, ">")) { + retval = strcmp(lhs, rhs) > 0; } else if (!strcmp(cmp, "!=")) { - if (!strcmp(lhs, rhs)) - vtc_log(hp->vl, 0, "EXPECT %s (%s) %s %s (%s) failed", - av[0], lhs, av[1], av[2], rhs); - else - vtc_log(hp->vl, 4, "EXPECT %s (%s) %s %s (%s) match", - av[0], lhs, av[1], av[2], rhs); + retval = strcmp(lhs, rhs) != 0; } else if (!strcmp(cmp, "~") || !strcmp(cmp, "!~")) { vre = VRE_compile(rhs, 0, &error, &erroroffset); if (vre == NULL) vtc_log(hp->vl, 0, "REGEXP error: %s (@%d) (%s)", error, erroroffset, rhs); i = VRE_exec(vre, lhs, strlen(lhs), 0, 0, NULL, 0, 0); - if ((i >= 0 && *cmp == '~') || (i < 0 && *cmp == '!')) - vtc_log(hp->vl, 4, "EXPECT %s (%s) %s \"%s\" match", - av[0], lhs, cmp, rhs); - else - vtc_log(hp->vl, 0, "EXPECT %s (%s) %s \"%s\" failed", - av[0], lhs, cmp, rhs); + retval = (i >= 0 && *cmp == '~') || (i < 0 && *cmp == '!'); VRE_free(&vre); - } else { + } + if (retval == -1) vtc_log(hp->vl, 0, "EXPECT %s (%s) %s %s (%s) test not implemented", av[0], lhs, av[1], av[2], rhs); - } + else + vtc_log(hp->vl, retval ? 4 : 0, "EXPECT %s (%s) %s \"%s\" %s", + av[0], lhs, cmp, rhs, retval ? "match" : "failed"); } /********************************************************************** From phk at varnish-cache.org Tue Sep 17 09:32:31 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 17 Sep 2013 11:32:31 +0200 Subject: [master] 0125de0 Turn obj.hits and obj.last_use (notice new '_', see below) into VCL only variables, and add a commented example in default.vcl. Message-ID: commit 0125de0eaa7a88f9170f4358cb5f9e731953b3e7 Author: Poul-Henning Kamp Date: Tue Sep 17 09:29:10 2013 +0000 Turn obj.hits and obj.last_use (notice new '_', see below) into VCL only variables, and add a commented example in default.vcl. The reason for this is to avoid VM write-backs to cached objects by default. Previously we did this with the obj_readonly parameter, but this puts it right where the user can see it. Notice that the two variables are not locked, so they cannot be trusted to be precise. obj.lastuse changes to obj.last_use because its type changes from DURATION to TIME, (and to improve readability in general) Fix & Polish relevant test-cases diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index f23241c..7647e9c 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -595,7 +595,6 @@ struct object { struct objcore *objcore; uint8_t *vary; - unsigned hits; uint16_t response; /* XXX: make bitmap */ @@ -609,6 +608,8 @@ struct object { struct exp exp; + /* VCL only variables */ + long hits; double last_modified; struct http *http; diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c index e2959fe..90af1fc 100644 --- a/bin/varnishd/cache/cache_hash.c +++ b/bin/varnishd/cache/cache_hash.c @@ -435,8 +435,6 @@ HSH_Lookup(struct req *req, struct objcore **ocp, struct objcore **bocp, oc->refcnt++; Lck_Unlock(&oh->mtx); assert(HSH_DerefObjHead(&wrk->stats, &oh)); - if (!cache_param->obj_readonly && o->hits < INT_MAX) - o->hits++; *ocp = oc; return (HSH_HIT); } diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index b0e7be7..812759c 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -108,8 +108,6 @@ cnt_deliver(struct worker *wrk, struct req *req) if ((req->t_resp - req->obj->objcore->last_lru) > cache_param->lru_timeout && EXP_Touch(req->obj->objcore)) req->obj->objcore->last_lru = req->t_resp; - if (!cache_param->obj_readonly) - req->obj->last_use = req->t_resp; /* XXX: locking ? */ } HTTP_Setup(req->resp, req->ws, req->vsl, HTTP_Resp); diff --git a/bin/varnishd/cache/cache_vrt_var.c b/bin/varnishd/cache/cache_vrt_var.c index a1c35f0..3d691a5 100644 --- a/bin/varnishd/cache/cache_vrt_var.c +++ b/bin/varnishd/cache/cache_vrt_var.c @@ -41,7 +41,6 @@ #include "vrt_obj.h" #include "vsa.h" #include "vtcp.h" -#include "vtim.h" static char vrt_hostname[255] = ""; @@ -609,26 +608,31 @@ VRT_r_server_port(const struct vrt_ctx *ctx) /*--------------------------------------------------------------------*/ -long -VRT_r_obj_hits(const struct vrt_ctx *ctx) -{ - - CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); - CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); - CHECK_OBJ_NOTNULL(ctx->req->obj, OBJECT_MAGIC); /* XXX */ - return (ctx->req->obj->hits); +#define VOBJ_L(type, field) \ +void \ +VRT_l_obj_##field(const struct vrt_ctx *ctx, type a) \ +{ \ + CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \ + CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); \ + CHECK_OBJ_NOTNULL(ctx->req->obj, OBJECT_MAGIC); \ + ctx->req->obj->field = a; \ } -double -VRT_r_obj_lastuse(const struct vrt_ctx *ctx) -{ - - CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); - CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); - CHECK_OBJ_NOTNULL(ctx->req->obj, OBJECT_MAGIC); /* XXX */ - return (VTIM_real() - ctx->req->obj->last_use); +#define VOBJ_R(type, field) \ +type \ +VRT_r_obj_##field(const struct vrt_ctx *ctx) \ +{ \ + CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \ + CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC); \ + CHECK_OBJ_NOTNULL(ctx->req->obj, OBJECT_MAGIC); \ + return (ctx->req->obj->field); \ } +VOBJ_L(long, hits) +VOBJ_R(long, hits) +VOBJ_L(double, last_use) +VOBJ_R(double, last_use) + unsigned VRT_r_obj_uncacheable(const struct vrt_ctx *ctx) { diff --git a/bin/varnishd/default.vcl b/bin/varnishd/default.vcl index 50e5da2..db64791 100644 --- a/bin/varnishd/default.vcl +++ b/bin/varnishd/default.vcl @@ -137,6 +137,13 @@ sub vcl_backend_response { } sub vcl_deliver { + /* + * These two write to the stored object causing extra page faults + * Enable them only if you need them. + * + * set obj.hits = obj.hits + 1; + * set obj.lastuse = now; + */ return (deliver); } diff --git a/bin/varnishd/mgt/mgt_param_tbl.c b/bin/varnishd/mgt/mgt_param_tbl.c index 6a0fc7c..c4a9566 100644 --- a/bin/varnishd/mgt/mgt_param_tbl.c +++ b/bin/varnishd/mgt/mgt_param_tbl.c @@ -603,11 +603,5 @@ const struct parspec mgt_parspec[] = { 0, "10,100,10", ""}, - { "obj_readonly", tweak_bool, &mgt_param.obj_readonly, 0, 0, - "If set, we do not update obj.hits and obj.lastuse to" - " avoid dirtying VM pages associated with cached objects.", - 0, - "false", "bool"}, - { NULL, NULL, NULL } }; diff --git a/bin/varnishd/storage/stevedore.c b/bin/varnishd/storage/stevedore.c index a7d0b44..a8203c4 100644 --- a/bin/varnishd/storage/stevedore.c +++ b/bin/varnishd/storage/stevedore.c @@ -284,6 +284,7 @@ STV_MkObject(struct stevedore *stv, struct busyobj *bo, HTTP_Setup(o->http, bo->ws_o, bo->vsl, HTTP_Obj); o->http->magic = HTTP_MAGIC; o->exp = bo->exp; + o->last_use = bo->exp.entered; VTAILQ_INIT(&o->store); bo->stats->n_object++; diff --git a/bin/varnishtest/tests/c00037.vtc b/bin/varnishtest/tests/c00037.vtc index e854a3b..e26be5b 100644 --- a/bin/varnishtest/tests/c00037.vtc +++ b/bin/varnishtest/tests/c00037.vtc @@ -13,13 +13,6 @@ varnish v1 -vcl+backend { set req.hash_always_miss = true; } } - sub vcl_deliver { - if(obj.hits > 0) { - set resp.http.X-Cache = "HIT"; - } else { - set resp.http.X-Cache = "MISS"; - } - } } -start client c1 { diff --git a/bin/varnishtest/tests/c00038.vtc b/bin/varnishtest/tests/c00038.vtc index 07e2657..ee396db 100644 --- a/bin/varnishtest/tests/c00038.vtc +++ b/bin/varnishtest/tests/c00038.vtc @@ -24,13 +24,6 @@ varnish v1 -vcl+backend { set req.backend = s2; } } - sub vcl_deliver { - if(obj.hits > 0) { - set resp.http.X-Cache = "HIT"; - } else { - set resp.http.X-Cache = "MISS"; - } - } } -start client c1 { diff --git a/bin/varnishtest/tests/r01073.vtc b/bin/varnishtest/tests/r01073.vtc index 936f8ce..b9f0e87 100644 --- a/bin/varnishtest/tests/r01073.vtc +++ b/bin/varnishtest/tests/r01073.vtc @@ -26,13 +26,6 @@ varnish v1 -vcl+backend { set req.backend = s2; } } - sub vcl_deliver { - if(obj.hits > 0) { - set resp.http.X-Cache = "HIT"; - } else { - set resp.http.X-Cache = "MISS"; - } - } } -start client c1 { diff --git a/bin/varnishtest/tests/v00013.vtc b/bin/varnishtest/tests/v00013.vtc index 031e484..882342f 100644 --- a/bin/varnishtest/tests/v00013.vtc +++ b/bin/varnishtest/tests/v00013.vtc @@ -1,4 +1,4 @@ -varnishtest "Check obj.hits" +varnishtest "Check obj.hits and obj.last_use" server s1 { rxreq @@ -13,6 +13,9 @@ varnish v1 -vcl+backend { sub vcl_deliver { set resp.http.foo = obj.hits; + set resp.http.bar = now - obj.last_use; + set obj.hits = obj.hits + 1; + set obj.last_use = now; } } -start @@ -31,9 +34,11 @@ client c1 { rxresp expect resp.status == 200 expect resp.http.foo == 0 + delay .1 txreq rxresp expect resp.status == 200 expect resp.http.foo == 2 + expect resp.http.bar >= 0.100 } -run diff --git a/bin/varnishtest/tests/v00025.vtc b/bin/varnishtest/tests/v00025.vtc index a191969..23c2530 100644 --- a/bin/varnishtest/tests/v00025.vtc +++ b/bin/varnishtest/tests/v00025.vtc @@ -7,46 +7,41 @@ server s1 { varnish v1 -vcl+backend { -sub vcl_deliver { - if (obj.lastuse > 3 s) { - set resp.http.lastuse = "then"; - } else { - set resp.http.lastuse = "now"; + sub vcl_deliver { + set resp.http.server_port = server.port; } - set resp.http.server_port = server.port; -} - -sub vcl_backend_response { - set beresp.http.backend = bereq.backend; - if (beresp.ttl > 3 s) { - set beresp.http.ttl = "long"; - } else { - set beresp.http.ttl = "short"; - } -} -sub vcl_hit { - if (obj.grace < 3m) { - set obj.grace = 1m; - } else { - set obj.grace = 2m; - } - if (obj.ttl < 3m) { - set obj.ttl = 2m; - } else { - set obj.ttl = 3m; + sub vcl_backend_response { + set beresp.http.backend = bereq.backend; + if (beresp.ttl > 3 s) { + set beresp.http.ttl = "long"; + } else { + set beresp.http.ttl = "short"; + } } -} -sub vcl_backend_fetch { - if (bereq.between_bytes_timeout < 10s) { - set bereq.http.quick = "please"; + sub vcl_hit { + if (obj.grace < 3m) { + set obj.grace = 1m; + } else { + set obj.grace = 2m; + } + if (obj.ttl < 3m) { + set obj.ttl = 2m; + } else { + set obj.ttl = 3m; + } } - if (bereq.connect_timeout < 10s) { - set bereq.http.hello = "please"; + + sub vcl_backend_fetch { + if (bereq.between_bytes_timeout < 10s) { + set bereq.http.quick = "please"; + } + if (bereq.connect_timeout < 10s) { + set bereq.http.hello = "please"; + } + set bereq.connect_timeout = 10s; } - set bereq.connect_timeout = 10s; -} } -start diff --git a/lib/libvcl/generate.py b/lib/libvcl/generate.py index 36be27b..012098a 100755 --- a/lib/libvcl/generate.py +++ b/lib/libvcl/generate.py @@ -375,7 +375,7 @@ sp_variables = [ ('obj.hits', 'INT', ( 'hit', 'deliver',), - ( ), + ( 'hit', 'deliver',), ), ('obj.http.', 'HEADER', @@ -397,10 +397,10 @@ sp_variables = [ ( 'hit', 'error',), ( 'hit', 'error',), ), - ('obj.lastuse', - 'DURATION', - ( 'hit', 'deliver', 'error',), - ( ), + ('obj.last_use', + 'TIME', + ( 'hit', 'deliver',), + ( 'hit', 'deliver',), ), ('obj.uncacheable', 'BOOL', From phk at varnish-cache.org Tue Sep 17 11:14:43 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 17 Sep 2013 13:14:43 +0200 Subject: [master] c4a12be Long overdue rename of libvcl to libvcc. Message-ID: commit c4a12be0d42232e32be44cdf85a0545d85d2df59 Author: Poul-Henning Kamp Date: Tue Sep 17 11:14:04 2013 +0000 Long overdue rename of libvcl to libvcc. diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am index da3480f..680deb1 100644 --- a/bin/varnishd/Makefile.am +++ b/bin/varnishd/Makefile.am @@ -118,7 +118,7 @@ varnishd_LDFLAGS = -export-dynamic varnishd_LDADD = \ $(top_builddir)/lib/libvarnish/libvarnish.la \ $(top_builddir)/lib/libvarnishcompat/libvarnishcompat.la \ - $(top_builddir)/lib/libvcl/libvcl.la \ + $(top_builddir)/lib/libvcc/libvcc.la \ $(top_builddir)/lib/libvgz/libvgz.la \ @JEMALLOC_LDADD@ \ @PCRE_LIBS@ \ diff --git a/bin/varnishd/cache/cache_backend_cfg.c b/bin/varnishd/cache/cache_backend_cfg.c index c217845..1fdf795 100644 --- a/bin/varnishd/cache/cache_backend_cfg.c +++ b/bin/varnishd/cache/cache_backend_cfg.c @@ -147,7 +147,7 @@ VBE_DropRefConn(struct backend *b) } /*-------------------------------------------------------------------- - * See lib/libvcl/vcc_backend.c::emit_sockaddr() + * See lib/libvcc/vcc_backend.c::emit_sockaddr() */ static void diff --git a/bin/varnishd/flint.sh b/bin/varnishd/flint.sh index 0694b78..b616a29 100755 --- a/bin/varnishd/flint.sh +++ b/bin/varnishd/flint.sh @@ -23,7 +23,7 @@ flexelint \ mgt/*.c \ ../../lib/libvarnish/*.c \ ../../lib/libvarnishcompat/execinfo.c \ - ../../lib/libvcl/*.c \ + ../../lib/libvcc/*.c \ ../../lib/libvmod_std/*.c \ ../../lib/libvmod_debug/*.c \ ../../lib/libvmod_directors/*.c \ diff --git a/bin/varnishd/mgt/mgt_vcc.c b/bin/varnishd/mgt/mgt_vcc.c index 28ac476..6701436 100644 --- a/bin/varnishd/mgt/mgt_vcc.c +++ b/bin/varnishd/mgt/mgt_vcc.c @@ -42,7 +42,7 @@ #include "common/params.h" #include "mgt/mgt.h" -#include "libvcl.h" +#include "libvcc.h" #include "vcl.h" #include "vcli.h" #include "vcli_priv.h" diff --git a/configure.ac b/configure.ac index 0bd07b6..0e73cf3 100644 --- a/configure.ac +++ b/configure.ac @@ -580,7 +580,7 @@ AC_CONFIG_FILES([ lib/libvarnishapi/Makefile lib/libvarnishtools/Makefile lib/libvarnishcompat/Makefile - lib/libvcl/Makefile + lib/libvcc/Makefile lib/libvgz/Makefile lib/libvmod_debug/Makefile lib/libvmod_std/Makefile diff --git a/include/Makefile.am b/include/Makefile.am index 605a71e..5b75aca 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -42,7 +42,7 @@ nobase_noinst_HEADERS = \ compat/execinfo.h \ compat/srandomdev.h \ flopen.h \ - libvcl.h \ + libvcc.h \ persistent.h \ vcli_common.h \ vcli_priv.h \ @@ -84,9 +84,9 @@ nobase_pkgdatainclude_HEADERS = \ vsb.h \ vsha256.h -tbl/vrt_stv_var.h tbl/vcl_returns.h tbl/vcc_types.h vcl.h vrt_obj.h: $(top_srcdir)/lib/libvcl/generate.py $(top_srcdir)/include/vrt.h +tbl/vrt_stv_var.h tbl/vcl_returns.h tbl/vcc_types.h vcl.h vrt_obj.h: $(top_srcdir)/lib/libvcc/generate.py $(top_srcdir)/include/vrt.h mkdir -p tbl - @PYTHON@ $(top_srcdir)/lib/libvcl/generate.py $(top_srcdir) $(top_builddir) + @PYTHON@ $(top_srcdir)/lib/libvcc/generate.py $(top_srcdir) $(top_builddir) BUILT_SOURCES = vcs_version.h vmod_abi.h MAINTAINERCLEANFILES = vcs_version.h diff --git a/include/libvcc.h b/include/libvcc.h new file mode 100644 index 0000000..5c50c34 --- /dev/null +++ b/include/libvcc.h @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2009 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +struct vcc; + +struct vcc *VCC_New(void); +void VCC_Default_VCL(struct vcc *, const char *str); +void VCC_VCL_dir(struct vcc *, const char *str); +void VCC_VMOD_dir(struct vcc *, const char *str); +void VCC_Err_Unref(struct vcc *tl, unsigned u); +void VCC_Allow_InlineC(struct vcc *tl, unsigned u); +void VCC_Unsafe_Path(struct vcc *tl, unsigned u); + +char *VCC_Compile(const struct vcc *, struct vsb *sb, const char *b); diff --git a/include/libvcl.h b/include/libvcl.h deleted file mode 100644 index 5c50c34..0000000 --- a/include/libvcl.h +++ /dev/null @@ -1,41 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2009 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -struct vcc; - -struct vcc *VCC_New(void); -void VCC_Default_VCL(struct vcc *, const char *str); -void VCC_VCL_dir(struct vcc *, const char *str); -void VCC_VMOD_dir(struct vcc *, const char *str); -void VCC_Err_Unref(struct vcc *tl, unsigned u); -void VCC_Allow_InlineC(struct vcc *tl, unsigned u); -void VCC_Unsafe_Path(struct vcc *tl, unsigned u); - -char *VCC_Compile(const struct vcc *, struct vsb *sb, const char *b); diff --git a/include/vrt.h b/include/vrt.h index 203bba1..e203168 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -28,7 +28,7 @@ * * Runtime support for compiled VCL programs. * - * XXX: When this file is changed, lib/libvcl/generate.py *MUST* be rerun. + * XXX: When this file is changed, lib/libvcc/generate.py *MUST* be rerun. */ struct req; diff --git a/lib/Makefile.am b/lib/Makefile.am index eb67436..c0c0e60 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -5,7 +5,7 @@ SUBDIRS = \ libvarnish \ libvarnishapi \ libvarnishtools \ - libvcl \ + libvcc \ libvgz \ libvmod_debug \ libvmod_std \ @@ -16,7 +16,7 @@ DIST_SUBDIRS = \ libvarnish \ libvarnishapi \ libvarnishtools \ - libvcl \ + libvcc \ libvgz \ libvmod_debug \ libvmod_std \ diff --git a/lib/libvcc/Makefile.am b/lib/libvcc/Makefile.am new file mode 100644 index 0000000..b030dc4 --- /dev/null +++ b/lib/libvcc/Makefile.am @@ -0,0 +1,44 @@ +# + +AM_LDFLAGS = $(AM_LT_LDFLAGS) + +AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include + +pkglib_LTLIBRARIES = libvcc.la + +libvcc_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version + +libvcc_la_SOURCES = \ + vcc_compile.h \ + vcc_token_defs.h \ + \ + vcc_acl.c \ + vcc_action.c \ + vcc_backend.c \ + vcc_backend_util.c \ + vcc_compile.c \ + vcc_expr.c \ + vcc_parse.c \ + vcc_fixed_token.c \ + vcc_obj.c \ + vcc_storage.c \ + vcc_utils.c \ + vcc_symb.c \ + vcc_token.c \ + vcc_var.c \ + vcc_vmod.c \ + vcc_xref.c + +EXTRA_DIST = \ + generate.py + +dist_pkgdata_SCRIPTS = \ + vmodtool.py + +vcc_obj.c vcc_fixed_token.c vcc_token_defs.h: \ + $(srcdir)/generate.py $(top_srcdir)/include/vrt.h + @PYTHON@ $(srcdir)/generate.py $(srcdir) $(top_builddir) + +CLEANFILES = $(builddir)/vcc_token_defs.h \ + $(builddir)/vcc_fixed_token.c \ + $(builddir)/vcc_obj.c diff --git a/lib/libvcc/flint.lnt b/lib/libvcc/flint.lnt new file mode 100644 index 0000000..60b3850 --- /dev/null +++ b/lib/libvcc/flint.lnt @@ -0,0 +1,46 @@ +-passes=3 + +// Review all below this line + +-printf_code( H, void *, unsigned) +-printf_code( ju, long long unsigned) +-printf_code( jx, long long unsigned) + ++libh ../../config.h +-header(../../config.h) +-sem(lbv_assert, r_no) +-sem(strchr, 1p, type(1), 2n == 0 ? (@p < 1p) : (@p < 1p || @p == 0 )) +-sem(vcc_new_source, custodial(1)) + +-emacro((???),va_arg) // the va_arg() macro can yield 415, 416, 661, 662 + // 796 and 797 (out-of-bounds errors). + + +-emacro(413, offsetof) // likely null pointer + +// -ffc // No automatic custody + +-esym(534, vsb_printf) // Ignoring return value of function +-esym(534, vsb_cat) // Ignoring return value of function +-esym(534, vsb_bcat) // Ignoring return value of function +-esym(534, vsb_vprintf) // Ignoring return value of function +-esym(534, memset) // Ignoring return value of function +-e788 // enum constant 'HND_Unclass' not used within defaulted switch +-e716 // while(1) ... +-e786 // String concatenation within initializer +-e732 // Loss of sign (arg. no. 2) (int to unsigned int) + + +-e763 // Redundant declaration for symbol '...' previously declared + + +-e737 // Loss of sign in promotion from int to unsigned int +-e534 // Ignoring return value of function +-e506 // Constant value boolean +-e774 // Boolean within 'if' always evaluates to False +-e713 // Loss of precision (assignment) (unsigned long long to long long) +-e574 // Signed-unsigned mix with relational +-e539 // Did not expect positive indentation +-e734 // Loss of precision (assignment) (31 bits to 8 bits) +-e747 // Significant prototype coercion (arg. no. 2) long +-e712 // Loss of precision (assignment) (long long to diff --git a/lib/libvcc/flint.sh b/lib/libvcc/flint.sh new file mode 100755 index 0000000..3bb465a --- /dev/null +++ b/lib/libvcc/flint.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +flexelint \ + -I/usr/include \ + -I. \ + -I../.. \ + -I../../include \ + -I../../contrib/libevent \ + flint.lnt \ + *.c diff --git a/lib/libvcc/generate.py b/lib/libvcc/generate.py new file mode 100755 index 0000000..3f20b08 --- /dev/null +++ b/lib/libvcc/generate.py @@ -0,0 +1,952 @@ +#!/usr/local/bin/python3.1 +#- +# Copyright (c) 2006 Verdens Gang AS +# Copyright (c) 2006-2013 Varnish Software AS +# All rights reserved. +# +# Author: Poul-Henning Kamp +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# Generate various .c and .h files for the VCL compiler and the interfaces +# for it. + +####################################################################### +# These are our tokens + +# We could drop all words such as "include", "if" etc, and use the +# ID type instead, but declaring them tokens makes them reserved words +# which hopefully makes for better error messages. +# XXX: does it actually do that ? + +import sys + +srcroot = "../.." +buildroot = "../.." +if len(sys.argv) == 3: + srcroot = sys.argv[1] + buildroot = sys.argv[2] + +tokens = { + "T_INC": "++", + "T_DEC": "--", + "T_CAND": "&&", + "T_COR": "||", + "T_LEQ": "<=", + "T_EQ": "==", + "T_NEQ": "!=", + "T_GEQ": ">=", + "T_SHR": ">>", + "T_SHL": "<<", + "T_INCR": "+=", + "T_DECR": "-=", + "T_MUL": "*=", + "T_DIV": "/=", + "T_NOMATCH": "!~", + + # Single char tokens, for convenience on one line + None: "{}()*+-/%><=;!&.|~,", + + # These have handwritten recognizers + "ID": None, + "CNUM": None, + "CSTR": None, + "EOI": None, + "CSRC": None, +} + +####################################################################### +# Our methods and actions + +returns =( + ('recv', "C", ('error', 'pass', 'pipe', 'hash', 'purge',)), + ('pipe', "C", ('error', 'pipe',)), + ('pass', "C", ('error', 'restart', 'fetch',)), + ('hash', "C", ('lookup',)), + ('purge', "C", ('error', 'fetch',)), + ('miss', "C", ('error', 'restart', 'pass', 'fetch',)), + ('hit', "C", ('error', 'restart', 'pass', 'fetch', 'deliver',)), + ('backend_fetch', "B", ('fetch', 'abandon')), + ('backend_response', "B", ('deliver', 'retry', 'abandon')), + ('deliver', "C", ('restart', 'deliver',)), + ('error', "C", ('restart', 'deliver',)), + ('init', "", ('ok',)), + ('fini', "", ('ok',)), +) + +####################################################################### +# Variables available in sessions +# +# 'all' means all methods +# 'client' means all methods tagged "C" +# 'backend' means all methods tagged "B" +# 'both' means all methods tagged "B" or "C" + +sp_variables = [ + ('client.ip', + 'IP', + ( 'both',), + ( ), + ), + ('client.identity', + 'STRING', + ( 'both',), + ( 'both',), + ), + ('server.ip', + 'IP', + ( 'client',), + ( ), + ), + ('server.hostname', + 'STRING', + ( 'client',), + ( ), + ), + ('server.identity', + 'STRING', + ( 'client',), + ( ), + ), + ('server.port', + 'INT', + ( 'client',), + ( ), + ), + ('req.method', + 'STRING', + ( 'client',), + ( 'client',), + ), + ('req.request', + 'STRING', + ( 'client',), + ( 'client',), + ), + ('req.url', + 'STRING', + ( 'client',), + ( 'client',), + ), + ('req.proto', + 'STRING', + ( 'client',), + ( 'client',), + ), + ('req.http.', + 'HEADER', + ( 'client',), + ( 'client',), + ), + ('req.restarts', + 'INT', + ( 'client',), + ( ), + ), + ('req.esi_level', + 'INT', + ( 'client',), + ( ), + ), + ('req.ttl', + 'DURATION', + ( 'client',), + ( 'client',), + ), + ('req.grace', + 'DURATION', + ( 'client',), + ( 'client',), + ), + ('req.keep', + 'DURATION', + ( 'client',), + ( 'client',), + ), + ('req.xid', + 'STRING', + ( 'client',), + ( ), + ), + ('req.esi', + 'BOOL', + ( 'recv', 'backend_response', 'deliver', 'error',), + ( 'recv', 'backend_response', 'deliver', 'error',), + ), + ('req.can_gzip', + 'BOOL', + ( 'client',), + ( ), + ), + ('req.backend', + 'BACKEND', + ( 'client',), + ( 'client',), + ), + ('req.backend.healthy', + 'BOOL', + ( 'client',), + ( ), + ), + ('req.hash_ignore_busy', + 'BOOL', + ( 'recv',), + ( 'recv',), + ), + ('req.hash_always_miss', + 'BOOL', + ( 'recv',), + ( 'recv',), + ), + ('bereq.retries', + 'INT', + ( 'backend',), + ( ), + ), + ('bereq.backend', + 'BACKEND', + ( 'pipe', 'backend', ), + ( 'pipe', 'backend', ), + ), + ('bereq.backend.healthy', + 'BOOL', + ( 'pipe', 'backend', ), + ( ), + ), + ('bereq.method', + 'STRING', + ( 'pipe', 'backend', ), + ( 'pipe', 'backend', ), + ), + ('bereq.request', + 'STRING', + ( 'pipe', 'backend', ), + ( 'pipe', 'backend', ), + ), + ('bereq.url', + 'STRING', + ( 'pipe', 'backend', ), + ( 'pipe', 'backend', ), + ), + ('bereq.proto', + 'STRING', + ( 'pipe', 'backend', ), + ( 'pipe', 'backend', ), + ), + ('bereq.http.', + 'HEADER', + ( 'pipe', 'backend', ), + ( 'pipe', 'backend', ), + ), + ('bereq.uncacheable', + 'BOOL', + ( 'backend', ), + ( 'backend', ), + ), + ('bereq.connect_timeout', + 'DURATION', + ( 'pipe', 'backend', ), + ( 'pipe', 'backend', ), + ), + ('bereq.first_byte_timeout', + 'DURATION', + ( 'pipe', 'backend', ), + ( 'pipe', 'backend', ), + ), + ('bereq.between_bytes_timeout', + 'DURATION', + ( 'pipe', 'backend', ), + ( 'pipe', 'backend', ), + ), + ('beresp.proto', + 'STRING', + ( 'backend_response',), + ( 'backend_response',), + ), + ('beresp.status', + 'INT', + ( 'backend_response',), + ( 'backend_response',), + ), + ('beresp.response', + 'STRING', + ( 'backend_response',), + ( 'backend_response',), + ), + ('beresp.http.', + 'HEADER', + ( 'backend_response',), + ( 'backend_response',), + ), + ('beresp.do_esi', + 'BOOL', + ( 'backend_response',), + ( 'backend_response',), + ), + ('beresp.do_stream', + 'BOOL', + ( 'backend_response',), + ( 'backend_response',), + ), + ('beresp.do_gzip', + 'BOOL', + ( 'backend_response',), + ( 'backend_response',), + ), + ('beresp.do_gunzip', + 'BOOL', + ( 'backend_response',), + ( 'backend_response',), + ), + ('beresp.uncacheable', + 'BOOL', + ( 'backend_response',), + ( 'backend_response',), + ), + ('beresp.ttl', + 'DURATION', + ( 'backend_response',), + ( 'backend_response',), + ), + ('beresp.grace', + 'DURATION', + ( 'backend_response',), + ( 'backend_response',), + ), + ('beresp.keep', + 'DURATION', + ( 'backend_response',), + ( 'backend_response',), + ), + ('beresp.backend.name', + 'STRING', + ( 'backend_response',), + ( ), + ), + ('beresp.backend.ip', + 'IP', + ( 'backend_response',), + ( ), + ), + ('beresp.backend.port', + 'INT', + ( 'backend_response',), + ( ), + ), + ('beresp.storage', + 'STRING', + ( 'backend_response',), + ( 'backend_response',), + ), + ('obj.proto', + 'STRING', + ( 'hit', 'error',), + ( 'hit', 'error',), + ), + ('obj.status', + 'INT', + ( 'error',), + ( 'error',), + ), + ('obj.response', + 'STRING', + ( 'error',), + ( 'error',), + ), + ('obj.hits', + 'INT', + ( 'hit', 'deliver',), + ( 'hit', 'deliver',), + ), + ('obj.http.', + 'HEADER', + ( 'hit', 'error',), + ( 'error',), # XXX ? + ), + ('obj.ttl', + 'DURATION', + ( 'hit', 'error',), + ( 'hit', 'error',), + ), + ('obj.grace', + 'DURATION', + ( 'hit', 'error',), + ( 'hit', 'error',), + ), + ('obj.keep', + 'DURATION', + ( 'hit', 'error',), + ( 'hit', 'error',), + ), + ('obj.last_use', + 'TIME', + ( 'hit', 'deliver',), + ( 'hit', 'deliver',), + ), + ('obj.uncacheable', + 'BOOL', + ( 'hit', 'deliver', 'error',), + ( ), + ), + ('resp.proto', + 'STRING', + ( 'deliver',), + ( 'deliver',), + ), + ('resp.status', + 'INT', + ( 'deliver',), + ( 'deliver',), + ), + ('resp.response', + 'STRING', + ( 'deliver',), + ( 'deliver',), + ), + ('resp.http.', + 'HEADER', + ( 'deliver',), + ( 'deliver',), + ), + ('now', + 'TIME', + ( 'all',), + ( ), + ), +] + +stv_variables = ( + ('free_space', 'BYTES', "0."), + ('used_space', 'BYTES', "0."), + ('happy', 'BOOL', "0"), +) + +####################################################################### +# VCL to C type conversion + +vcltypes = { + 'STRING_LIST': "void*", +} + +fi = open(srcroot + "/include/vrt.h") + +for i in fi: + j = i.split(); + if len(j) < 3: + continue + if j[0] != "typedef": + continue + if j[-1][-1] != ";": + continue + if j[-1][:4] != "VCL_": + continue + d = " ".join(j[1:-1]) + vcltypes[j[-1][4:-1]] = d +fi.close() + +####################################################################### +# Nothing is easily configurable below this line. +####################################################################### + +import sys +import copy + +####################################################################### +# Emit a function to recognize tokens in a string + +def emit_vcl_fixed_token(fo, tokens): + + recog = list() + emit = dict() + for i in tokens: + j = tokens[i] + if (j != None): + recog.append(j) + emit[j] = i + + recog.sort() + rrecog = copy.copy(recog) + rrecog.sort(key = lambda x: -len(x)) + + fo.write(""" +#define M1()\tdo {*q = p + 1; return (p[0]); } while (0) +#define M2(c,t)\tdo {if (p[1] == (c)) { *q = p + 2; return (t); }} while (0) + +unsigned +vcl_fixed_token(const char *p, const char **q) +{ + +\tswitch (p[0]) { +""") + last_initial = None + for i in recog: + if (i[0] == last_initial): + continue + last_initial = i[0] + fo.write("\tcase '%s':\n" % last_initial) + need_ret = True + for j in rrecog: + if (j[0] != last_initial): + continue + if len(j) == 2: + fo.write("\t\tM2('%s', %s);\n" % + (j[1], emit[j])) + elif len(j) == 1: + fo.write("\t\tM1();\n") + need_ret = False + else: + fo.write("\t\tif (") + k = 1 + l = len(j) + while (k < l): + fo.write("p[%d] == '%s'" % (k, j[k])) + fo.write(" &&") + if (k % 3) == 0: + fo.write("\n\t\t ") + else: + fo.write(" ") + k += 1 + fo.write("!isvar(p[%d])) {\n" % l) + fo.write("\t\t\t*q = p + %d;\n" % l) + fo.write("\t\t\treturn (%s);\n" % emit[j]) + fo.write("\t\t}\n") + if need_ret: + fo.write("\t\treturn (0);\n") + fo.write("\tdefault:\n\t\treturn (0);\n\t}\n}\n") + +####################################################################### +# Emit the vcl_tnames (token->string) conversion array + +def emit_vcl_tnames(fo, tokens): + fo.write("\nconst char * const vcl_tnames[256] = {\n") + l = list(tokens.keys()) + l.sort() + for i in l: + j = tokens[i] + if j == None: + j = i + if i[0] == "'": + j = i + fo.write("\t[%s] = \"%s\",\n" % (i, j)) + fo.write("};\n") + +####################################################################### +# Read a C-source file and spit out code that outputs it with VSB_cat() + +def emit_file(fo, fn): + fi = open(fn) + fc = fi.read() + fi.close() + + w = 66 # Width of lines, after white space prefix + maxlen = 10240 # Max length of string literal + + x = 0 + l = 0 + fo.write("\n\t/* %s */\n\n" % fn) + for c in fc: + if l == 0: + fo.write("\tVSB_cat(sb, \"") + l += 12 + x += 12 + if x == 0: + fo.write("\t \"") + d = c + if c == '\n': + d = "\\n" + elif c == '\t': + d = "\\t" + elif c == '"': + d = "\\\"" + elif c == '\\': + d = "\\\\" + + if c == '\n' and x > w - 20: + fo.write(d + "\"\n") + x = 0 + continue + if c.isspace() and x > w - 10: + fo.write(d + "\"\n") + x = 0 + continue + + fo.write(d) + x += len(d) + l += len(d) + if l > maxlen: + fo.write("\");\n") + l = 0; + x = 0 + if x > w - 3: + fo.write("\"\n") + x = 0 + if x != 0: + fo.write("\"") + if l != 0: + fo.write("\t);\n") + +####################################################################### + +def polish_tokens(tokens): + # Expand single char tokens + st = tokens[None] + del tokens[None] + + for i in st: + tokens["'" + i + "'"] = i +####################################################################### + +def file_header(fo): + fo.write("""/* + * NB: This file is machine generated, DO NOT EDIT! + * + * Edit and run generate.py instead + */ +""") + +####################################################################### + +polish_tokens(tokens) + +fo = open(buildroot + "/lib/libvcc/vcc_token_defs.h", "w") + +file_header(fo) + +j = 128 +l = list(tokens.keys()) +l.sort() +for i in l: + if i[0] == "'": + continue + fo.write("#define\t%s %d\n" % (i, j)) + j += 1 + assert j < 256 + +fo.close() + +####################################################################### + +rets = dict() +vcls = list() +vcls_client = list() +vcls_backend = list() +for i in returns: + vcls.append(i[0]) + for j in i[1]: + if j == "B": + vcls_backend.append(i[0]) + elif j == "C": + vcls_client.append(i[0]) + for j in i[2]: + rets[j] = True + +####################################################################### + +fo = open(buildroot + "/include/tbl/vcl_returns.h", "w") + +file_header(fo) + +fo.write("\n/*lint -save -e525 -e539 */\n") + +fo.write("\n#ifdef VCL_RET_MAC\n") +l = list(rets.keys()) +l.sort() +for i in l: + fo.write("VCL_RET_MAC(%s, %s" % (i.lower(), i.upper())) + s=", " + for j in returns: + if i in j[2]: + fo.write("%sVCL_MET_%s" % (s, j[0].upper())) + s = " | " + fo.write(")\n") +fo.write("#endif\n") + +fo.write("\n#ifdef VCL_MET_MAC\n") +for i in returns: + fo.write("VCL_MET_MAC(%s,%s,\n" % (i[0].lower(), i[0].upper())) + p = " (" + for j in i[2]: + fo.write(" %s(1U << VCL_RET_%s)\n" % (p, j.upper())) + p = "| " + fo.write("))\n") +fo.write("#endif\n") +fo.write("\n/*lint -restore */\n") +fo.close() + +####################################################################### + +fo = open(buildroot + "/include/vcl.h", "w") + +file_header(fo) + +fo.write(""" +struct vrt_ctx; +struct req; +struct busyobj; +struct ws; +struct cli; +struct worker; + +typedef int vcl_init_f(struct cli *); +typedef void vcl_fini_f(struct cli *); +typedef int vcl_func_f(const struct vrt_ctx *ctx); +""") + + +fo.write("\n/* VCL Methods */\n") +n = 0 +for i in returns: + fo.write("#define VCL_MET_%s\t\t(1U << %d)\n" % (i[0].upper(), n)) + n += 1 + +fo.write("\n#define VCL_MET_MAX\t\t%d\n" % n) +fo.write("\n#define VCL_MET_MASK\t\t0x%x\n" % ((1 << n) - 1)) + + +fo.write("\n/* VCL Returns */\n") +n = 0 +l = list(rets.keys()) +l.sort() +for i in l: + fo.write("#define VCL_RET_%s\t\t%d\n" % (i.upper(), n)) + n += 1 + +fo.write("\n#define VCL_RET_MAX\t\t%d\n" % n) + + +fo.write(""" +struct VCL_conf { + unsigned magic; +#define VCL_CONF_MAGIC 0x7406c509 /* from /dev/random */ + + struct director **director; + unsigned ndirector; + struct vrt_ref *ref; + unsigned nref; + unsigned busy; + unsigned discard; + + unsigned nsrc; + const char **srcname; + const char **srcbody; + + vcl_init_f *init_vcl; + vcl_fini_f *fini_vcl; +""") + +for i in returns: + fo.write("\tvcl_func_f\t*" + i[0] + "_func;\n") + +fo.write(""" +}; +""") + +fo.close() + +####################################################################### + +def restrict(fo, spec): + d = dict() + for j in spec: + if j == 'all': + for i in vcls: + d[i] = True + elif j == 'backend': + for i in vcls_backend: + d[i] = True + elif j == 'client': + for i in vcls_client: + d[i] = True + elif j == 'both': + for i in vcls_client: + d[i] = True + for i in vcls_backend: + d[i] = True + else: + assert j in vcls + d[j] = True + p = "" + n = 0 + l = list(d.keys()) + l.sort() + w = 0 + fo.write("\t\t") + for j in l: + x = p + "VCL_MET_" + j.upper() + if w + len(x) > 60: + fo.write("\n\t\t") + w = 0 + fo.write(x) + w += len(x) + p = " | " + if len(d) == 0: + fo.write("0") + fo.write(",\n") + +####################################################################### + +fh = open(buildroot + "/include/vrt_obj.h", "w") +file_header(fh) + +fo = open(buildroot + "/lib/libvcc/vcc_obj.c", "w") +file_header(fo) + +fo.write(""" +#include "config.h" + +#include + +#include "vcc_compile.h" + +const struct var vcc_vars[] = { +""") + +sp_variables.sort() +for i in sp_variables: + typ = i[1] + cnam = i[0].replace(".", "_") + ctyp = vcltypes[typ] + + fo.write("\t{ \"%s\", %s, %d,\n" % (i[0], typ, len(i[0]))) + + if len(i[2]) == 0: + fo.write('\t NULL,\t/* No reads allowed */\n') + elif typ == "HEADER": + fo.write('\t "HDR_') + fo.write(i[0].split(".")[0].upper()) + fo.write('",\n') + else: + fo.write('\t "VRT_r_%s(ctx)",\n' % cnam) + fh.write(ctyp + " VRT_r_%s(const struct vrt_ctx *);\n" % cnam ) + restrict(fo, i[2]) + + if len(i[3]) == 0: + fo.write('\t NULL,\t/* No writes allowed */\n') + elif typ == "HEADER": + fo.write('\t "HDR_') + fo.write(i[0].split(".")[0].upper()) + fo.write('",\n') + else: + fo.write('\t "VRT_l_%s(ctx, ",\n' % cnam) + fh.write("void VRT_l_%s(const struct vrt_ctx *, " % cnam) + if typ != "STRING": + fh.write(ctyp + ");\n") + else: + fh.write(ctyp + ", ...);\n") + restrict(fo, i[3]) + + fo.write("\t},\n") + +fo.write("\t{ NULL }\n};\n") + +for i in stv_variables: + fh.write(vcltypes[i[1]] + " VRT_Stv_" + i[0] + "(const char *);\n") + +fo.close() +fh.close() + +####################################################################### + +fo = open(buildroot + "/lib/libvcc/vcc_fixed_token.c", "w") + +file_header(fo) +fo.write(""" + +#include "config.h" + +#include +#include + +#include "vcc_compile.h" +""") + +emit_vcl_fixed_token(fo, tokens) +emit_vcl_tnames(fo, tokens) + +fo.write(""" +void +vcl_output_lang_h(struct vsb *sb) +{ +""") + +emit_file(fo, buildroot + "/include/vcl.h") +emit_file(fo, srcroot + "/include/vrt.h") +emit_file(fo, buildroot + "/include/vrt_obj.h") + +fo.write(""" +} +""") + +fo.close() + +####################################################################### +ft = open(buildroot + "/include/tbl/vcc_types.h", "w") +file_header(ft) + +ft.write("/*lint -save -e525 -e539 */\n") + +i = list(vcltypes.keys()) +i.sort() +for j in i: + ft.write("VCC_TYPE(" + j + ")\n") +ft.write("/*lint -restore */\n") +ft.close() + +####################################################################### + +fo = open(buildroot + "/include/tbl/vrt_stv_var.h", "w") + +file_header(fo) + +fo.write(""" +#ifndef VRTSTVTYPE +#define VRTSTVTYPE(ct) +#define VRTSTVTYPEX +#endif +#ifndef VRTSTVVAR +#define VRTSTVVAR(nm, vtype, ctype, dval) +#define VRTSTVVARX +#endif +""") + +x=dict() +for i in stv_variables: + ct = vcltypes[i[1]] + if not ct in x: + fo.write("VRTSTVTYPE(" + ct + ")\n") + x[ct] = 1 + fo.write("VRTSTVVAR(" + i[0] + ",\t" + i[1] + ",\t") + fo.write(ct + ",\t" + i[2] + ")") + fo.write("\n") + +fo.write(""" +#ifdef VRTSTVTYPEX +#undef VRTSTVTYPEX +#undef VRTSTVTYPE +#endif +#ifdef VRTSTVVARX +#undef VRTSTVVARX +#undef VRTSTVVAR +#endif +""") + +fo.close diff --git a/lib/libvcc/vcc_acl.c b/lib/libvcc/vcc_acl.c new file mode 100644 index 0000000..fa8a7d7 --- /dev/null +++ b/lib/libvcc/vcc_acl.c @@ -0,0 +1,502 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2010 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include + +#include + +#include +#include +#include +#include + +#include "vcc_compile.h" + +#include "vrt.h" + +struct acl_e { + VTAILQ_ENTRY(acl_e) list; + unsigned char data[VRT_ACL_MAXADDR + 1]; + unsigned mask; + unsigned not; + unsigned para; + struct token *t_addr; + struct token *t_mask; +}; + +/* Compare two acl rules for ordering */ + +#define CMP(a, b) \ + do { \ + if ((a) < (b)) \ + return (-1); \ + else if ((b) < (a)) \ + return (1); \ + } while (0) + +static int +vcl_acl_cmp(struct acl_e *ae1, struct acl_e *ae2) +{ + unsigned char *p1, *p2; + unsigned m; + + p1 = ae1->data; + p2 = ae2->data; + m = ae1->mask; + if (ae2->mask < m) + m = ae2->mask; + for (; m >= 8; m -= 8) { + CMP(*p1, *p2); + p1++; + p2++; + } + if (m) { + m = 0xff00 >> m; + m &= 0xff; + CMP(*p1 & m, *p2 & m); + } + /* Long mask is less than short mask */ + CMP(ae2->mask, ae1->mask); + + return (0); +} + + +static void +vcc_acl_add_entry(struct vcc *tl, const struct acl_e *ae, int l, + const unsigned char *u, int fam) +{ + struct acl_e *ae2, *aen; + int i; + + if (fam == PF_INET && ae->mask > 32) { + VSB_printf(tl->sb, + "Too wide mask (%u) for IPv4 address\n", ae->mask); + if (ae->t_mask != NULL) + vcc_ErrWhere(tl, ae->t_mask); + else + vcc_ErrWhere(tl, ae->t_addr); + return; + } + if (fam == PF_INET6 && ae->mask > 128) { + VSB_printf(tl->sb, + "Too wide mask (%u) for IPv6 address\n", ae->mask); + vcc_ErrWhere(tl, ae->t_mask); + return; + } + + /* Make a copy from the template */ + aen = TlAlloc(tl, sizeof *ae2); + AN(aen); + *aen = *ae; + + /* We treat family as part of address, it saves code */ + assert(fam <= 0xff); + aen->data[0] = fam & 0xff; + aen->mask += 8; + + memcpy(aen->data + 1, u, l); + + VTAILQ_FOREACH(ae2, &tl->acl, list) { + i = vcl_acl_cmp(aen, ae2); + if (i == 0) { + /* + * If the two rules agree, silently ignore it + * XXX: is that counter intuitive ? + */ + if (aen->not == ae2->not) + return; + VSB_printf(tl->sb, "Conflicting ACL entries:\n"); + vcc_ErrWhere(tl, ae2->t_addr); + VSB_printf(tl->sb, "vs:\n"); + vcc_ErrWhere(tl, aen->t_addr); + return; + } + /* + * We could eliminate pointless rules here, for instance in: + * "10.1.0.1"; + * "10.1"; + * The first rule is clearly pointless, as the second one + * covers it. + * + * We do not do this however, because the shmlog may + * be used to gather statistics. + */ + if (i < 0) { + VTAILQ_INSERT_BEFORE(ae2, aen, list); + return; + } + } + VTAILQ_INSERT_TAIL(&tl->acl, aen, list); +} + +static void +vcc_acl_try_getaddrinfo(struct vcc *tl, struct acl_e *ae) +{ + struct addrinfo *res0, *res, hint; + struct sockaddr_in *sin4; + struct sockaddr_in6 *sin6; + unsigned char *u, i4, i6; + int error; + + memset(&hint, 0, sizeof hint); + hint.ai_family = PF_UNSPEC; + hint.ai_socktype = SOCK_STREAM; + error = getaddrinfo(ae->t_addr->dec, "0", &hint, &res0); + if (error) { + if (ae->para) { + VSB_printf(tl->sb, + "Warning: %s ignored\n -- %s\n", + ae->t_addr->dec, gai_strerror(error)); + Fh(tl, 1, "/* Ignored ACL entry: %s%s", + ae->para ? "\"(\" " : "", ae->not ? "\"!\" " : ""); + EncToken(tl->fh, ae->t_addr); + if (ae->t_mask) + Fh(tl, 0, "/%u", ae->mask); + Fh(tl, 0, "%s\n", ae->para ? " \")\"" : ""); + Fh(tl, 1, " * getaddrinfo: %s */\n", + gai_strerror(error)); + } else { + VSB_printf(tl->sb, + "DNS lookup(%s): %s\n", + ae->t_addr->dec, gai_strerror(error)); + vcc_ErrWhere(tl, ae->t_addr); + } + return; + } + + i4 = i6 = 0; + for(res = res0; res != NULL; res = res->ai_next) { + switch(res->ai_family) { + case PF_INET: + assert(PF_INET < 256); + sin4 = (void*)res->ai_addr; + assert(sizeof(sin4->sin_addr) == 4); + u = (void*)&sin4->sin_addr; + if (ae->t_mask == NULL) + ae->mask = 32; + i4++; + vcc_acl_add_entry(tl, ae, 4, u, res->ai_family); + break; + case PF_INET6: + assert(PF_INET6 < 256); + sin6 = (void*)res->ai_addr; + assert(sizeof(sin6->sin6_addr) == 16); + u = (void*)&sin6->sin6_addr; + if (ae->t_mask == NULL) + ae->mask = 128; + i6++; + vcc_acl_add_entry(tl, ae, 16, u, res->ai_family); + break; + default: + VSB_printf(tl->sb, + "Ignoring unknown protocol family (%d) for %.*s\n", + res->ai_family, PF(ae->t_addr)); + continue; + } + ERRCHK(tl); + } + freeaddrinfo(res0); + + if (ae->t_mask != NULL && i4 > 0 && i6 > 0) { + VSB_printf(tl->sb, + "Mask (%u) specified, but string resolves to" + " both IPv4 and IPv6 addresses.\n", ae->mask); + vcc_ErrWhere(tl, ae->t_mask); + return; + } +} + +/*-------------------------------------------------------------------- + * Ancient stupidity on the part of X/Open and other standards orgs + * dictate that "192.168" be translated to 192.0.0.168. Ever since + * CIDR happened, "192.168/16" notation has been used, but appearantly + * no API supports parsing this, so roll our own. + */ + +static int +vcc_acl_try_netnotation(struct vcc *tl, struct acl_e *ae) +{ + unsigned char b[4]; + int i, j, k; + unsigned u; + const char *p; + + memset(b, 0, sizeof b); + p = ae->t_addr->dec; + for (i = 0; i < 4; i++) { + j = sscanf(p, "%u%n", &u, &k); + if (j != 1) + return (0); + if (u & ~0xff) + return (0); + b[i] = (unsigned char)u; + if (p[k] == '\0') + break; + if (p[k] != '.') + return (0); + p += k + 1; + } + if (ae->t_mask == NULL) + ae->mask = 8 + 8 * i; + vcc_acl_add_entry(tl, ae, 4, b, AF_INET); + return (1); +} + +static void +vcc_acl_entry(struct vcc *tl) +{ + struct acl_e *ae; + + ae = TlAlloc(tl, sizeof *ae); + AN(ae); + + if (tl->t->tok == '!') { + ae->not = 1; + vcc_NextToken(tl); + } + + if (tl->t->tok == '(') { + ae->para = 1; + vcc_NextToken(tl); + } + + if (!ae->not && tl->t->tok == '!') { + ae->not = 1; + vcc_NextToken(tl); + } + + ExpectErr(tl, CSTR); + ae->t_addr = tl->t; + vcc_NextToken(tl); + + if (tl->t->tok == '/') { + vcc_NextToken(tl); + ae->t_mask = tl->t; + ExpectErr(tl, CNUM); + ae->mask = vcc_UintVal(tl); + } + + if (ae->para) + SkipToken(tl, ')'); + + if (!vcc_acl_try_netnotation(tl, ae)) { + ERRCHK(tl); + vcc_acl_try_getaddrinfo(tl, ae); + } + ERRCHK(tl); +} + +/********************************************************************* + * Emit a function to match the ACL we have collected + */ + +/* + * XXX: this is semi-silly. We try really hard to not depend in the + * XXX: systems include files while compiling VCL, but we need to know + * XXX: the size of the sa_familiy member. + * XXX: FlexeLint complains about these antics, so isolate it in a + * XXX: separate function. + */ + +/*lint -save -e506 -e774 -e550 */ +static void +c_is_a_silly_language(const struct vcc *tl) +{ + struct sockaddr sa; + + assert(sizeof (unsigned char) == 1); + assert(sizeof (unsigned short) == 2); + assert(sizeof (unsigned int) == 4); + if (sizeof sa.sa_family == 1) + Fh(tl, 0, "\tunsigned char fam;\n"); + else if (sizeof sa.sa_family == 2) + Fh(tl, 0, "\tunsigned short fam;\n"); + else if (sizeof sa.sa_family == 4) + Fh(tl, 0, "\tunsigned int fam;\n"); + else + assert(0 == __LINE__); +} +/*lint -restore */ + +static void +vcc_acl_emit(const struct vcc *tl, const char *acln, int anon) +{ + struct acl_e *ae; + int depth, l, m, i; + unsigned at[VRT_ACL_MAXADDR + 1]; + const char *oc; + + Fh(tl, 0, "\nstatic int\n"); + Fh(tl, 0, "match_acl_%s_%s(const struct vrt_ctx *ctx, const void *p)\n", + anon ? "anon" : "named", acln); + Fh(tl, 0, "{\n"); + Fh(tl, 0, "\tconst unsigned char *a;\n"); + c_is_a_silly_language(tl); + + Fh(tl, 0, "\n"); + Fh(tl, 0, "\ta = p;\n"); + Fh(tl, 0, "\tVRT_memmove(&fam, a + %zd, sizeof fam);\n", + offsetof(struct sockaddr, sa_family)); + Fh(tl, 0, "\tif (fam == %d)\n", PF_INET); + Fh(tl, 0, "\t\ta += %zd;\n", offsetof(struct sockaddr_in, sin_addr)); + Fh(tl, 0, "\telse if (fam == %d)\n", PF_INET6); + Fh(tl, 0, "\t\ta += %zd;\n", offsetof(struct sockaddr_in6, sin6_addr)); + Fh(tl, 0, "\telse {\n"); + Fh(tl, 0, "\t\tVRT_acl_log(ctx, \"NO_FAM %s\");\n", acln); + Fh(tl, 0, "\t\treturn(0);\n"); + Fh(tl, 0, "\t}\n\n"); + depth = -1; + oc = 0; + at[0] = 256; + VTAILQ_FOREACH(ae, &tl->acl, list) { + + /* Find how much common prefix we have */ + for (l = 0; l <= depth && l * 8 < ae->mask - 7; l++) { + assert(l >= 0); + if (ae->data[l] != at[l]) + break; + } + + /* Back down, if necessary */ + oc = ""; + while (l <= depth) { + Fh(tl, 0, "\t%*s}\n", -depth, ""); + depth--; + } + + m = ae->mask; + m -= l * 8; + assert(m >= 0); + + /* Do whole byte compares */ + for (i = l; m >= 8; m -= 8, i++) { + if (i == 0) + Fh(tl, 0, "\t%*s%sif (fam == %d) {\n", + -i, "", oc, ae->data[i]); + else + Fh(tl, 0, "\t%*s%sif (a[%d] == %d) {\n", + -i, "", oc, i - 1, ae->data[i]); + at[i] = ae->data[i]; + depth = i; + oc = ""; + } + + if (m > 0) { + /* Do fractional byte compares */ + Fh(tl, 0, "\t%*s%sif ((a[%d] & 0x%x) == %d) {\n", + -i, "", oc, i - 1, (0xff00 >> m) & 0xff, + ae->data[i] & ((0xff00 >> m) & 0xff)); + at[i] = 256; + depth = i; + oc = ""; + } + + i = (ae->mask + 7) / 8; + + if (!anon) { + Fh(tl, 0, "\t%*sVRT_acl_log(ctx, \"%sMATCH %s \" ", + -i, "", ae->not ? "NEG_" : "", acln); + EncToken(tl->fh, ae->t_addr); + if (ae->t_mask != NULL) + Fh(tl, 0, " \"/%.*s\" ", PF(ae->t_mask)); + Fh(tl, 0, ");\n"); + } + + Fh(tl, 0, "\t%*sreturn (%d);\n", -i, "", ae->not ? 0 : 1); + } + + /* Unwind */ + for (; 0 <= depth; depth--) + Fh(tl, 0, "\t%*.*s}\n", depth, depth, ""); + + /* Deny by default */ + if (!anon) + Fh(tl, 0, "\tVRT_acl_log(ctx, \"NO_MATCH %s\");\n", acln); + Fh(tl, 0, "\treturn (0);\n}\n"); +} + +void +vcc_Acl_Hack(struct vcc *tl, char *b) +{ + char acln[32]; + unsigned tcond; + + VTAILQ_INIT(&tl->acl); + tcond = tl->t->tok; + vcc_NextToken(tl); + bprintf(acln, "%u", tl->unique++); + vcc_acl_entry(tl); + vcc_acl_emit(tl, acln, 1); + sprintf(b, "%smatch_acl_anon_%s(ctx, \v1)", + (tcond == T_NEQ ? "!" : ""), acln); +} + +void +vcc_Acl(struct vcc *tl) +{ + struct token *an; + int i; + char acln[1024]; + + vcc_NextToken(tl); + VTAILQ_INIT(&tl->acl); + + ExpectErr(tl, ID); + if (!vcc_isCid(tl->t)) { + VSB_printf(tl->sb, + "Names of VCL acl's cannot contain '-'\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + an = tl->t; + vcc_NextToken(tl); + + i = vcc_AddDef(tl, an, SYM_ACL); + if (i > 1) { + VSB_printf(tl->sb, "ACL %.*s redefined\n", PF(an)); + vcc_ErrWhere(tl, an); + return; + } + bprintf(acln, "%.*s", PF(an)); + + SkipToken(tl, '{'); + + while (tl->t->tok != '}') { + vcc_acl_entry(tl); + ERRCHK(tl); + SkipToken(tl, ';'); + } + SkipToken(tl, '}'); + + vcc_acl_emit(tl, acln, 0); +} diff --git a/lib/libvcc/vcc_action.c b/lib/libvcc/vcc_action.c new file mode 100644 index 0000000..4e441d2 --- /dev/null +++ b/lib/libvcc/vcc_action.c @@ -0,0 +1,445 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file parses the real action of the VCL code, the procedure + * statements which do the actual work. + */ + +#include "config.h" + +#include + +#include "vcc_compile.h" + +/*--------------------------------------------------------------------*/ + +static void +parse_call(struct vcc *tl) +{ + + vcc_NextToken(tl); + ExpectErr(tl, ID); + vcc_AddCall(tl, tl->t); + vcc_AddRef(tl, tl->t, SYM_SUB); + Fb(tl, 1, "if (VGC_function_%.*s(ctx))\n", PF(tl->t)); + Fb(tl, 1, "\treturn (1);\n"); + vcc_NextToken(tl); + return; +} + +/*--------------------------------------------------------------------*/ + +static void +parse_error(struct vcc *tl) +{ + + VSB_printf(tl->sb, + "Syntax has changed, use:\n" + "\treturn(error(999));\n" + "or\n" + "\treturn(error(999, \"Response text\"));\n"); + vcc_ErrWhere(tl, tl->t); + return; +} + +/*--------------------------------------------------------------------*/ + +static const struct arith { + enum var_type type; + unsigned oper; + enum var_type want; +} arith[] = { + { INT, T_INCR, INT }, + { INT, T_DECR, INT }, + { INT, T_MUL, INT }, + { INT, T_DIV, INT }, + { INT, '=', INT }, + { INT, 0, INT }, + { TIME, T_INCR, DURATION }, + { TIME, T_DECR, DURATION }, + { TIME, T_MUL, REAL }, + { TIME, T_DIV, REAL }, + { TIME, '=', TIME }, + { TIME, 0, TIME }, + { DURATION, T_INCR, DURATION }, + { DURATION, T_DECR, DURATION }, + { DURATION, T_MUL, REAL }, + { DURATION, T_DIV, REAL }, + { DURATION, '=', DURATION }, + { DURATION, 0, DURATION }, + { VOID, '=', VOID } +}; + +static void +parse_set(struct vcc *tl) +{ + const struct var *vp; + const struct arith *ap; + enum var_type fmt; + + vcc_NextToken(tl); + ExpectErr(tl, ID); + vp = vcc_FindVar(tl, tl->t, 1, "cannot be set"); + ERRCHK(tl); + assert(vp != NULL); + Fb(tl, 1, "%s\n", vp->lname); + tl->indent += INDENT; + vcc_NextToken(tl); + fmt = vp->fmt; + for (ap = arith; ap->type != VOID; ap++) { + if (ap->type != fmt) + continue; + if (ap->oper != tl->t->tok) + continue; + if (ap->oper != '=') + Fb(tl, 1, "%s %c ", vp->rname, *tl->t->b); + vcc_NextToken(tl); + fmt = ap->want; + break; + } + if (ap->type == VOID) + SkipToken(tl, ap->oper); + if (fmt == HEADER) { + vcc_Expr(tl, STRING_LIST); + } else if (fmt == STRING) { + vcc_Expr(tl, STRING_LIST); + } else { + vcc_Expr(tl, fmt); + } + tl->indent -= INDENT; + Fb(tl, 1, ");\n"); +} + +/*--------------------------------------------------------------------*/ + +static void +parse_unset(struct vcc *tl) +{ + const struct var *vp; + + /* XXX: Wrong, should use VCC_Expr(HEADER) */ + vcc_NextToken(tl); + ExpectErr(tl, ID); + vp = vcc_FindVar(tl, tl->t, 1, "cannot be unset"); + ERRCHK(tl); + assert(vp != NULL); + if (vp->fmt != HEADER) { + VSB_printf(tl->sb, + "Only http header variables can be unset.\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + ERRCHK(tl); + Fb(tl, 1, "%svrt_magic_string_unset);\n", vp->lname); + vcc_NextToken(tl); +} + +/*--------------------------------------------------------------------*/ + +static void +parse_new(struct vcc *tl) +{ + struct symbol *sy1, *sy2, *sy3; + const char *p, *s_obj, *s_init, *s_struct, *s_fini; + char buf1[128]; + char buf2[128]; + + vcc_NextToken(tl); + ExpectErr(tl, ID); + if (!vcc_isCid(tl->t)) { + VSB_printf(tl->sb, + "Names of VCL objects cannot contain '-'\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + sy1 = VCC_FindSymbol(tl, tl->t, SYM_NONE); + XXXAZ(sy1); + + sy1 = VCC_AddSymbolTok(tl, tl->t, SYM_NONE); // XXX: NONE ? + XXXAN(sy1); + vcc_NextToken(tl); + + ExpectErr(tl, '='); + vcc_NextToken(tl); + + ExpectErr(tl, ID); + sy2 = VCC_FindSymbol(tl, tl->t, SYM_OBJECT); + XXXAN(sy2); + + /*lint -save -e448 */ + /* Split the first three args */ + p = sy2->args; + s_obj = p; + p += strlen(p) + 1; + s_init = p; + while (p[0] != '\0' || p[1] != '\0') + p++; + p += 2; + s_struct = p; + p += strlen(p) + 1; + s_fini = p + strlen(p) + 1; + while (p[0] != '\0' || p[1] != '\0') + p++; + p += 2; + + Fh(tl, 0, "static %s *%s;\n\n", s_struct, sy1->name); + + vcc_NextToken(tl); + + bprintf(buf1, ", &%s, \"%s\"", sy1->name, sy1->name); + vcc_Eval_Func(tl, s_init, buf1, "ASDF", s_init + strlen(s_init) + 1); + Fd(tl, 0, "\t%s(&%s);\n", s_fini, sy1->name); + ExpectErr(tl, ';'); + + bprintf(buf1, ", %s", sy1->name); + /* Split the methods from the args */ + while (*p != '\0') { + p += strlen(s_obj); + bprintf(buf2, "%s%s", sy1->name, p); + sy3 = VCC_AddSymbolStr(tl, buf2, SYM_FUNC); + AN(sy3); + sy3->eval = vcc_Eval_SymFunc; + p += strlen(p) + 1; + sy3->cfunc = p; + p += strlen(p) + 1; + + /* Functions which return VOID are procedures */ + if (!memcmp(p, "VOID\0", 5)) + sy3->kind = SYM_PROC; + + sy3->args = p; + sy3->extra = TlDup(tl, buf1); + while (p[0] != '\0' || p[1] != '\0') { + if (!memcmp(p, "ENUM\0", 5)) { + /* XXX: Special case for ENUM that has + it's own \0\0 end marker. Not exactly + elegant, we should consider + alternatives here. Maybe runlength + encode the entire block? */ + p += strlen(p) + 1; + while (p[0] != '\0' || p[1] != '\0') + p++; + } + p++; + } + p += 2; + } + /*lint -restore */ +} + +/*--------------------------------------------------------------------*/ + +static void +parse_ban(struct vcc *tl) +{ + + vcc_NextToken(tl); + + ExpectErr(tl, '('); + vcc_NextToken(tl); + + Fb(tl, 1, "VRT_ban_string(\n"); + tl->indent += INDENT; + vcc_Expr(tl, STRING); + tl->indent -= INDENT; + ERRCHK(tl); + Fb(tl, 1, ");\n"); + + ExpectErr(tl, ')'); + vcc_NextToken(tl); +} + +/*--------------------------------------------------------------------*/ + +static void +parse_hash_data(struct vcc *tl) +{ + vcc_NextToken(tl); + SkipToken(tl, '('); + + Fb(tl, 1, "VRT_hashdata(ctx, "); + vcc_Expr(tl, STRING_LIST); + ERRCHK(tl); + Fb(tl, 0, ");\n"); + SkipToken(tl, ')'); +} + +/*--------------------------------------------------------------------*/ + +static void +parse_return(struct vcc *tl) +{ + int retval = 0; + + vcc_NextToken(tl); + ExpectErr(tl, '('); + vcc_NextToken(tl); + ExpectErr(tl, ID); + + /* 'error' gets special handling, to allow optional status/response */ + if (vcc_IdIs(tl->t, "error")) { + vcc_NextToken(tl); + if (tl->t->tok == ')') { + VSB_printf(tl->sb, + "Syntax has changed, use:\n" + "\treturn(error(999));\n" + "or\n" + "\treturn(error(999, \"Response text\"));\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + ExpectErr(tl, '('); + vcc_NextToken(tl); + Fb(tl, 1, "VRT_error(ctx,\n"); + tl->indent += INDENT; + vcc_Expr(tl, INT); + ERRCHK(tl); + Fb(tl, 1, ",\n"); + if (tl->t->tok == ',') { + vcc_NextToken(tl); + vcc_Expr(tl, STRING); + ERRCHK(tl); + } else { + Fb(tl, 1, "(const char*)0\n"); + } + tl->indent -= INDENT; + ExpectErr(tl, ')'); + vcc_NextToken(tl); + Fb(tl, 1, ");\n"); + Fb(tl, 1, "VRT_handling(ctx, VCL_RET_ERROR);\n"); + Fb(tl, 1, "return (1);\n"); + vcc_ProcAction(tl->curproc, VCL_RET_ERROR, tl->t); + ExpectErr(tl, ')'); + vcc_NextToken(tl); + return; + } + +#define VCL_RET_MAC(l, U, B) \ + do { \ + if (vcc_IdIs(tl->t, #l)) { \ + Fb(tl, 1, "VRT_handling(ctx, VCL_RET_" #U ");\n"); \ + Fb(tl, 1, "return (1);\n"); \ + vcc_ProcAction(tl->curproc, VCL_RET_##U, tl->t);\ + retval = 1; \ + } \ + } while (0); +#include "tbl/vcl_returns.h" +#undef VCL_RET_MAC + if (!retval) { + VSB_printf(tl->sb, "Expected return action name.\n"); + vcc_ErrWhere(tl, tl->t); + ERRCHK(tl); + } + vcc_NextToken(tl); + ExpectErr(tl, ')'); + vcc_NextToken(tl); +} + +/*--------------------------------------------------------------------*/ + +static void +parse_rollback(struct vcc *tl) +{ + + vcc_NextToken(tl); + Fb(tl, 1, "VRT_Rollback(ctx);\n"); +} + +/*--------------------------------------------------------------------*/ + +static void +parse_purge(struct vcc *tl) +{ + + vcc_NextToken(tl); + Fb(tl, 1, "VRT_purge(ctx, 0, 0);\n"); +} + +/*--------------------------------------------------------------------*/ + +static void +parse_synthetic(struct vcc *tl) +{ + vcc_NextToken(tl); + + Fb(tl, 1, "VRT_synth_page(ctx, 0, "); + vcc_Expr(tl, STRING_LIST); + ERRCHK(tl); + Fb(tl, 0, ");\n"); +} + +/*--------------------------------------------------------------------*/ + +typedef void action_f(struct vcc *tl); + +static struct action_table { + const char *name; + action_f *func; + unsigned bitmask; +} action_table[] = { + /* Keep list sorted from here */ + { "ban", parse_ban }, + { "call", parse_call }, + { "error", parse_error }, + { "hash_data", parse_hash_data, VCL_MET_HASH }, + { "new", parse_new, VCL_MET_INIT}, + { "purge", parse_purge, VCL_MET_MISS | VCL_MET_HIT }, + { "remove", parse_unset }, /* backward compatibility */ + { "return", parse_return }, + { "rollback", parse_rollback }, + { "set", parse_set }, + { "synthetic", parse_synthetic, VCL_MET_ERROR }, + { "unset", parse_unset }, + { NULL, NULL } +}; + +int +vcc_ParseAction(struct vcc *tl) +{ + struct token *at; + struct action_table *atp; + const struct symbol *sym; + + at = tl->t; + assert(at->tok == ID); + for(atp = action_table; atp->name != NULL; atp++) { + if (vcc_IdIs(at, atp->name)) { + if (atp->bitmask != 0) + vcc_AddUses(tl, at, atp->bitmask, + "not a valid action"); + atp->func(tl); + return (1); + } + } + sym = VCC_FindSymbol(tl, tl->t, SYM_NONE); + if (sym != NULL && sym->kind == SYM_PROC) { + vcc_Expr_Call(tl, sym); + return (1); + } + return (0); +} diff --git a/lib/libvcc/vcc_backend.c b/lib/libvcc/vcc_backend.c new file mode 100644 index 0000000..b548d94 --- /dev/null +++ b/lib/libvcc/vcc_backend.c @@ -0,0 +1,484 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "config.h" + +#include +#include + +#include "vcc_compile.h" + +#include "vss.h" + +/*-------------------------------------------------------------------- + * Struct sockaddr is not really designed to be a compile time + * initialized data structure, so we encode it as a byte-string + * and put it in an official sockaddr when we load the VCL. + */ + +static void +Emit_Sockaddr(struct vcc *tl, const struct token *t_host, const char *port) +{ + const char *ipv4, *ipv4a, *ipv6, *ipv6a, *pa; + const char *err; + char *hop, *pop; + + AN(t_host->dec); + + err = VSS_parse(t_host->dec, &hop, &pop); + if (err != NULL) { + VSB_printf(tl->sb, + "Backend host '%.*s': %s\n", PF(t_host), err); + vcc_ErrWhere(tl, t_host); + return; + } + Resolve_Sockaddr(tl, + hop != NULL ? hop : t_host->dec, + pop != NULL ? pop : port, + &ipv4, &ipv4a, &ipv6, &ipv6a, &pa, 2, t_host, "Backend host"); + ERRCHK(tl); + if (ipv4 != NULL) { + Fb(tl, 0, "\t.ipv4_sockaddr = %s,\n", ipv4); + Fb(tl, 0, "\t.ipv4_addr = \"%s\",\n", ipv4a); + } + if (ipv6 != NULL) { + Fb(tl, 0, "\t.ipv6_sockaddr = %s,\n", ipv6); + Fb(tl, 0, "\t.ipv6_addr = \"%s\",\n", ipv6a); + } + Fb(tl, 0, "\t.port = \"%s\",\n", pa); +} + +/*-------------------------------------------------------------------- + * Parse a backend probe specification + */ + +static void +vcc_ProbeRedef(struct vcc *tl, struct token **t_did, + struct token *t_field) +{ + /* .url and .request are mutually exclusive */ + + if (*t_did != NULL) { + VSB_printf(tl->sb, "Probe request redefinition at:\n"); + vcc_ErrWhere(tl, t_field); + VSB_printf(tl->sb, "Previous definition:\n"); + vcc_ErrWhere(tl, *t_did); + return; + } + *t_did = t_field; +} + +static void +vcc_ParseProbeSpec(struct vcc *tl) +{ + struct fld_spec *fs; + struct token *t_field; + struct token *t_did = NULL, *t_window = NULL, *t_threshold = NULL; + struct token *t_initial = NULL; + unsigned window, threshold, initial, status; + double t; + + fs = vcc_FldSpec(tl, + "?url", + "?request", + "?expected_response", + "?timeout", + "?interval", + "?window", + "?threshold", + "?initial", + NULL); + + SkipToken(tl, '{'); + + window = 0; + threshold = 0; + initial = 0; + status = 0; + Fh(tl, 0, "static const struct vrt_backend_probe vgc_probe__%d = {\n", + tl->nprobe++); + while (tl->t->tok != '}') { + + vcc_IsField(tl, &t_field, fs); + ERRCHK(tl); + if (vcc_IdIs(t_field, "url")) { + vcc_ProbeRedef(tl, &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_ProbeRedef(tl, &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, '}'); +} + +/*-------------------------------------------------------------------- + * Parse and emit a probe definition + */ + +void +vcc_ParseProbe(struct vcc *tl) +{ + struct token *t_probe; + int i; + + vcc_NextToken(tl); /* ID: probe */ + + vcc_ExpectCid(tl); /* ID: name */ + ERRCHK(tl); + t_probe = tl->t; + vcc_NextToken(tl); + i = vcc_AddDef(tl, t_probe, SYM_PROBE); + if (i > 1) { + VSB_printf(tl->sb, "Probe %.*s redefined\n", PF(t_probe)); + vcc_ErrWhere(tl, t_probe); + } + + Fh(tl, 0, "\n#define vgc_probe_%.*s\tvgc_probe__%d\n", + PF(t_probe), tl->nprobe); + vcc_ParseProbeSpec(tl); +} + +/*-------------------------------------------------------------------- + * Parse and emit a backend host definition + * + * The struct vrt_backend is emitted to Fh(). + */ + +static void +vcc_ParseHostDef(struct vcc *tl, const struct token *t_be) +{ + struct token *t_field; + struct token *t_host = NULL; + struct token *t_port = NULL; + struct token *t_hosthdr = NULL; + struct fld_spec *fs; + struct vsb *vsb; + unsigned u; + double t; + char vgcname[MAX_BACKEND_NAME + 8]; + + sprintf(vgcname, "_%.*s", PF(t_be)); + + 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", + 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(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, "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, 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); + 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"); + + /* 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,\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++; +} + +/*-------------------------------------------------------------------- + * Parse directors and backends + */ + +void +vcc_ParseBackend(struct vcc *tl) +{ + struct token *t_first, *t_be; + int isfirst; + struct symbol *sym; + + t_first = tl->t; + vcc_NextToken(tl); /* ID: backend */ + + vcc_ExpectCid(tl); /* ID: name */ + ERRCHK(tl); + + if (tl->t->e - tl->t->b > MAX_BACKEND_NAME) { + VSB_printf(tl->sb, + "Name of %.*s too long (max %d, is %zu):\n", + PF(t_first), MAX_BACKEND_NAME, + (size_t)(tl->t->e - tl->t->b)); + vcc_ErrWhere(tl, tl->t); + return; + } + + t_be = tl->t; + vcc_NextToken(tl); + + isfirst = tl->ndirector; + + sym = VCC_GetSymbolTok(tl, t_be, SYM_BACKEND); + AN(sym); + if (sym->ndef > 0) { + VSB_printf(tl->sb, "Backend %.*s redefined\n", PF(t_be)); + vcc_ErrWhere(tl, t_be); + return; + } + sym->fmt = BACKEND; + sym->eval = vcc_Eval_Backend; + sym->ndef++; + ERRCHK(tl); + + vcc_ParseHostDef(tl, t_be); + ERRCHK(tl); + + if (tl->err) { + VSB_printf(tl->sb, + "\nIn %.*s specification starting at:\n", PF(t_first)); + vcc_ErrWhere(tl, t_first); + return; + } + + if (isfirst == 1 || vcc_IdIs(t_be, "default")) { + tl->defaultdir = tl->ndirector - 1; + tl->t_defaultdir = t_be; + } +} diff --git a/lib/libvcc/vcc_backend_util.c b/lib/libvcc/vcc_backend_util.c new file mode 100644 index 0000000..de361a5 --- /dev/null +++ b/lib/libvcc/vcc_backend_util.c @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2011 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "config.h" + +#include +#include +#include + +#include "vcc_compile.h" + +/*-------------------------------------------------------------------- + * Helper functions to complain about duplicate and missing fields + * + * XXX: idea: add groups to check for exclusivity, such that + * XXX: ("!foo", "?bar", "!{", "this", "that", "}", NULL) + * XXX: means exactly one of "this" or "that", and + * XXX: ("!foo", "?bar", "?{", "this", "that", "}", NULL) + * XXX: means at most one of "this" or "that". + */ + +struct fld_spec { + const char *name; + struct token *found; +}; + +static void +vcc_ResetFldSpec(struct fld_spec *f) +{ + + for (; f->name != NULL; f++) + f->found = NULL; +} + +struct fld_spec * +vcc_FldSpec(struct vcc *tl, const char *first, ...) +{ + struct fld_spec f[100], *r; + int n = 0; + va_list ap; + const char *p; + + f[n++].name = first; + va_start(ap, first); + while (1) { + p = va_arg(ap, const char *); + if (p == NULL) + break; + f[n++].name = p; + assert(n < 100); + } + va_end(ap); + f[n++].name = NULL; + + vcc_ResetFldSpec(f); + + r = TlAlloc(tl, sizeof *r * n); + memcpy(r, f, n * sizeof *r); + return (r); +} + +void +vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs) +{ + struct token *t_field; + + SkipToken(tl, '.'); + ExpectErr(tl, ID); + t_field = tl->t; + *t = t_field; + vcc_NextToken(tl); + SkipToken(tl, '='); + + for (; fs->name != NULL; fs++) { + if (!vcc_IdIs(t_field, fs->name + 1)) + continue; + if (fs->found == NULL) { + fs->found = t_field; + return; + } + VSB_printf(tl->sb, "Field "); + vcc_ErrToken(tl, t_field); + VSB_printf(tl->sb, " redefined at:\n"); + vcc_ErrWhere(tl, t_field); + VSB_printf(tl->sb, "\nFirst defined at:\n"); + vcc_ErrWhere(tl, fs->found); + return; + } + VSB_printf(tl->sb, "Unknown field: "); + vcc_ErrToken(tl, t_field); + VSB_printf(tl->sb, " at\n"); + vcc_ErrWhere(tl, t_field); + return; +} + +void +vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs) +{ + + for (; fs->name != NULL; fs++) { + if (*fs->name == '!' && fs->found == NULL) { + VSB_printf(tl->sb, + "Mandatory field '%s' missing.\n", fs->name + 1); + tl->err = 1; + } + } +} diff --git a/lib/libvcc/vcc_compile.c b/lib/libvcc/vcc_compile.c new file mode 100644 index 0000000..1b3ee4e --- /dev/null +++ b/lib/libvcc/vcc_compile.c @@ -0,0 +1,823 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * XXX: + * Better error messages, throughout. + * >It also accured to me that we could link the errors to the error + * >documentation. + * > + * >Unreferenced function 'request_policy', first mention is + * > Line 8 Pos 4 + * > sub request_policy { + * > ----##############-- + * >Read more about this type of error: + * >http://varnish/doc/error.html#Unreferenced%20function + * > + * > + * > Unknown variable 'obj.bandwidth' + * > At: Line 88 Pos 12 + * > if (obj.bandwidth < 1 kb/h) { + * > ------------#############------------ + * >Read more about this type of error: + * >http://varnish/doc/error.html#Unknown%20variable + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "vcc_compile.h" + +#include "libvcc.h" +#include "vfil.h" + +struct method method_tab[] = { +#define VCL_MET_MAC(l,U,m) { "vcl_"#l, m, VCL_MET_##U }, +#include "tbl/vcl_returns.h" +#undef VCL_MET_MAC + { NULL, 0U, 0} +}; + +/*--------------------------------------------------------------------*/ + +static void +TlDoFree(struct vcc *tl, void *p) +{ + struct membit *mb; + + mb = calloc(sizeof *mb, 1); + assert(mb != NULL); + mb->ptr = p; + VTAILQ_INSERT_TAIL(&tl->membits, mb, list); +} + + +void * +TlAlloc(struct vcc *tl, unsigned len) +{ + void *p; + + p = calloc(len, 1); + assert(p != NULL); + TlDoFree(tl, p); + return (p); +} + +char * +TlDup(struct vcc *tl, const char *s) +{ + char *p; + + p = TlAlloc(tl, strlen(s) + 1); + AN(p); + strcpy(p, s); + return (p); +} + +char * +TlDupTok(struct vcc *tl, const struct token *tok) +{ + char *p; + int i; + + i = tok->e - tok->b; + p = TlAlloc(tl, i + 1); + AN(p); + memcpy(p, tok->b, i); + p[i] = '\0'; + return (p); +} + +/*--------------------------------------------------------------------*/ + +int +IsMethod(const struct token *t) +{ + struct method *m; + + assert(t->tok == ID); + for(m = method_tab; m->name != NULL; m++) { + if (vcc_IdIs(t, m->name)) + return (m - method_tab); + } + if ((t->b[0] == 'v'|| t->b[0] == 'V') && + (t->b[1] == 'c'|| t->b[1] == 'C') && + (t->b[2] == 'l'|| t->b[2] == 'L')) + return (-2); + return (-1); +} + +/*-------------------------------------------------------------------- + * Printf output to the vsbs, possibly indented + */ + +void +Fh(const struct vcc *tl, int indent, const char *fmt, ...) +{ + va_list ap; + + if (indent) + VSB_printf(tl->fh, "%*.*s", tl->hindent, tl->hindent, ""); + va_start(ap, fmt); + VSB_vprintf(tl->fh, fmt, ap); + va_end(ap); +} + +void +Fb(const struct vcc *tl, int indent, const char *fmt, ...) +{ + va_list ap; + + assert(tl->fb != NULL); + if (indent) + VSB_printf(tl->fb, "%*.*s", tl->indent, tl->indent, ""); + va_start(ap, fmt); + VSB_vprintf(tl->fb, fmt, ap); + va_end(ap); +} + +void +Fc(const struct vcc *tl, int indent, const char *fmt, ...) +{ + va_list ap; + + if (indent) + VSB_printf(tl->fc, "%*.*s", tl->indent, tl->indent, ""); + va_start(ap, fmt); + VSB_vprintf(tl->fc, fmt, ap); + va_end(ap); +} + +void +Fi(const struct vcc *tl, int indent, const char *fmt, ...) +{ + va_list ap; + + if (indent) + VSB_printf(tl->fi, "%*.*s", tl->iindent, tl->iindent, ""); + va_start(ap, fmt); + VSB_vprintf(tl->fi, fmt, ap); + va_end(ap); +} + +void +Fd(const struct vcc *tl, int indent, const char *fmt, ...) +{ + va_list ap; + + if (indent) + VSB_printf(tl->fd, "%*.*s", tl->findent, tl->findent, ""); + va_start(ap, fmt); + VSB_vprintf(tl->fd, fmt, ap); + va_end(ap); +} + + +void +Ff(const struct vcc *tl, int indent, const char *fmt, ...) +{ + va_list ap; + + if (indent) + VSB_printf(tl->ff, "%*.*s", tl->findent, tl->findent, ""); + va_start(ap, fmt); + VSB_vprintf(tl->ff, fmt, ap); + va_end(ap); +} + +/*--------------------------------------------------------------------*/ + +void +EncString(struct vsb *sb, const char *b, const char *e, int mode) +{ + + if (e == NULL) + e = strchr(b, '\0'); + + VSB_cat(sb, "\""); + for (; b < e; b++) { + switch (*b) { + case '\\': + case '"': + VSB_printf(sb, "\\%c", *b); + break; + case '\n': + VSB_printf(sb, "\\n"); + if (mode) + VSB_printf(sb, "\"\n\t\""); + break; + case '\t': VSB_printf(sb, "\\t"); break; + case '\r': VSB_printf(sb, "\\r"); break; + case ' ': VSB_printf(sb, " "); break; + default: + if (isgraph(*b)) + VSB_printf(sb, "%c", *b); + else + VSB_printf(sb, "\\%03o", (uint8_t)*b); + break; + } + } + VSB_cat(sb, "\""); +} + +void +EncToken(struct vsb *sb, const struct token *t) +{ + + assert(t->tok == CSTR); + EncString(sb, t->dec, NULL, 1); +} + +/*-------------------------------------------------------------------- + * Output the location/profiling table. For each counted token, we + * record source+line+charpos for the first character in the token. + */ + +static void +LocTable(const struct vcc *tl) +{ + struct token *t; + unsigned lin, pos; + struct source *sp; + const char *p; + + Fh(tl, 0, "\n#define VGC_NREFS %u\n", tl->cnt + 1); + Fc(tl, 0, "\nstatic struct vrt_ref VGC_ref[VGC_NREFS] = {\n"); + lin = 1; + pos = 0; + sp = 0; + p = NULL; + VTAILQ_FOREACH(t, &tl->tokens, list) { + if (t->cnt == 0) + continue; + assert(t->src != NULL); + if (t->src != sp) { + lin = 1; + pos = 0; + sp = t->src; + p = sp->b; + } + assert(sp != NULL); + assert(p != NULL); + for (;p < t->b; p++) { + if (*p == '\n') { + lin++; + pos = 0; + } else if (*p == '\t') { + pos &= ~7; + pos += 8; + } else + pos++; + + } + Fc(tl, 0, " [%3u] = { %d, %8tu, %4u, %3u, 0, ", + t->cnt, sp->idx, t->b - sp->b, lin, pos + 1); + if (t->tok == CSRC) + Fc(tl, 0, " \"C{\"},\n"); + else + Fc(tl, 0, " \"%.*s\" },\n", PF(t)); + } + Fc(tl, 0, "};\n"); +} + +/*--------------------------------------------------------------------*/ + +static void +EmitInitFunc(const struct vcc *tl) +{ + + Fc(tl, 0, "\nstatic int\nVGC_Init(struct cli *cli)\n{\n\n"); + AZ(VSB_finish(tl->fi)); + VSB_cat(tl->fc, VSB_data(tl->fi)); + Fc(tl, 0, "\treturn(0);\n"); + Fc(tl, 0, "}\n"); +} + +static void +EmitFiniFunc(const struct vcc *tl) +{ + unsigned u; + + Fc(tl, 0, "\nstatic void\nVGC_Fini(struct cli *cli)\n{\n\n"); + + AZ(VSB_finish(tl->fd)); + VSB_cat(tl->fc, VSB_data(tl->fd)); + + /* + * We do this here, so we are sure they happen before any + * per-vcl vmod_privs get cleaned. + */ + for (u = 0; u < tl->nvmodpriv; u++) + Fc(tl, 0, "\tvmod_priv_fini(&vmod_priv_%u);\n", u); + + AZ(VSB_finish(tl->ff)); + VSB_cat(tl->fc, VSB_data(tl->ff)); + Fc(tl, 0, "}\n"); +} + +/*--------------------------------------------------------------------*/ + +static void +EmitStruct(const struct vcc *tl) +{ + struct source *sp; + + Fc(tl, 0, "\nconst char *srcname[%u] = {\n", tl->nsources); + VTAILQ_FOREACH(sp, &tl->sources, list) { + Fc(tl, 0, "\t"); + EncString(tl->fc, sp->name, NULL, 0); + Fc(tl, 0, ",\n"); + } + Fc(tl, 0, "};\n"); + + Fc(tl, 0, "\nconst char *srcbody[%u] = {\n", tl->nsources); + VTAILQ_FOREACH(sp, &tl->sources, list) { + Fc(tl, 0, " /* "); + EncString(tl->fc, sp->name, NULL, 0); + Fc(tl, 0, "*/\n"); + Fc(tl, 0, "\t"); + EncString(tl->fc, sp->b, sp->e, 1); + Fc(tl, 0, ",\n"); + } + Fc(tl, 0, "};\n"); + + Fc(tl, 0, "\nstatic struct director\t*directors[%d];\n", + tl->ndirector); + + Fc(tl, 0, "\nconst struct VCL_conf VCL_conf = {\n"); + Fc(tl, 0, "\t.magic = VCL_CONF_MAGIC,\n"); + Fc(tl, 0, "\t.init_vcl = VGC_Init,\n"); + Fc(tl, 0, "\t.fini_vcl = VGC_Fini,\n"); + Fc(tl, 0, "\t.ndirector = %d,\n", tl->ndirector); + Fc(tl, 0, "\t.director = directors,\n"); + Fc(tl, 0, "\t.ref = VGC_ref,\n"); + Fc(tl, 0, "\t.nref = VGC_NREFS,\n"); + Fc(tl, 0, "\t.nsrc = %u,\n", tl->nsources); + Fc(tl, 0, "\t.srcname = srcname,\n"); + Fc(tl, 0, "\t.srcbody = srcbody,\n"); +#define VCL_MET_MAC(l,u,b) \ + Fc(tl, 0, "\t." #l "_func = VGC_function_vcl_" #l ",\n"); +#include "tbl/vcl_returns.h" +#undef VCL_MET_MAC + Fc(tl, 0, "};\n"); +} + +/*--------------------------------------------------------------------*/ + +static struct source * +vcc_new_source(const char *b, const char *e, const char *name) +{ + struct source *sp; + + if (e == NULL) + e = strchr(b, '\0'); + sp = calloc(sizeof *sp, 1); + assert(sp != NULL); + sp->name = strdup(name); + AN(sp->name); + sp->b = b; + sp->e = e; + return (sp); +} + +static void +vcc_destroy_source(struct source *sp) +{ + + if (sp->freeit != NULL) + free(sp->freeit); + free(sp->name); + free(sp); +} + +/*--------------------------------------------------------------------*/ + +static struct source * +vcc_file_source(const struct vcc *tl, struct vsb *sb, const char *fn) +{ + char *f; + struct source *sp; + + if (!tl->unsafe_path && strchr(fn, '/') != NULL) { + VSB_printf(sb, "Include path is unsafe '%s'\n", fn); + return (NULL); + } + f = VFIL_readfile(tl->vcl_dir, fn, NULL); + if (f == NULL) { + VSB_printf(sb, "Cannot read file '%s': %s\n", + fn, strerror(errno)); + return (NULL); + } + sp = vcc_new_source(f, NULL, fn); + sp->freeit = f; + return (sp); +} + +/*--------------------------------------------------------------------*/ + +static void +vcc_resolve_includes(struct vcc *tl) +{ + struct token *t, *t1, *t2; + struct source *sp; + + VTAILQ_FOREACH(t, &tl->tokens, list) { + if (t->tok != ID || !vcc_IdIs(t, "include")) + continue; + + t1 = VTAILQ_NEXT(t, list); + assert(t1 != NULL); /* There's always an EOI */ + if (t1->tok != CSTR) { + VSB_printf(tl->sb, + "include not followed by string constant.\n"); + vcc_ErrWhere(tl, t1); + return; + } + t2 = VTAILQ_NEXT(t1, list); + assert(t2 != NULL); /* There's always an EOI */ + + if (t2->tok != ';') { + VSB_printf(tl->sb, + "include not followed by semicolon.\n"); + vcc_ErrWhere(tl, t1); + return; + } + + sp = vcc_file_source(tl, tl->sb, t1->dec); + if (sp == NULL) { + vcc_ErrWhere(tl, t1); + return; + } + VTAILQ_INSERT_TAIL(&tl->sources, sp, list); + sp->idx = tl->nsources++; + tl->t = t2; + vcc_Lexer(tl, sp); + + VTAILQ_REMOVE(&tl->tokens, t, list); + VTAILQ_REMOVE(&tl->tokens, t1, list); + VTAILQ_REMOVE(&tl->tokens, t2, list); + if (!tl->err) + vcc_resolve_includes(tl); + return; + } +} + +/*--------------------------------------------------------------------*/ + +static struct vcc * +vcc_NewVcc(const struct vcc *tl0) +{ + struct vcc *tl; + int i; + + ALLOC_OBJ(tl, VCC_MAGIC); + AN(tl); + if (tl0 != NULL) { + REPLACE(tl->default_vcl, tl0->default_vcl); + REPLACE(tl->vcl_dir, tl0->vcl_dir); + REPLACE(tl->vmod_dir, tl0->vmod_dir); + tl->vars = tl0->vars; + tl->err_unref = tl0->err_unref; + tl->allow_inline_c = tl0->allow_inline_c; + tl->unsafe_path = tl0->unsafe_path; + } else { + tl->err_unref = 1; + } + VTAILQ_INIT(&tl->symbols); + VTAILQ_INIT(&tl->membits); + VTAILQ_INIT(&tl->tokens); + VTAILQ_INIT(&tl->sources); + + tl->nsources = 0; + tl->ndirector = 1; + + /* General C code */ + tl->fc = VSB_new_auto(); + assert(tl->fc != NULL); + + /* Forward decls (.h like) */ + tl->fh = VSB_new_auto(); + assert(tl->fh != NULL); + + /* Init C code */ + tl->fi = VSB_new_auto(); + assert(tl->fi != NULL); + + /* Destroy Objects */ + tl->fd = VSB_new_auto(); + assert(tl->fd != NULL); + + /* Finish C code */ + tl->ff = VSB_new_auto(); + assert(tl->ff != NULL); + + /* body code of methods */ + for (i = 0; i < VCL_MET_MAX; i++) { + tl->fm[i] = VSB_new_auto(); + assert(tl->fm[i] != NULL); + } + return (tl); +} + +/*--------------------------------------------------------------------*/ + +static char * +vcc_DestroyTokenList(struct vcc *tl, char *ret) +{ + struct membit *mb; + struct source *sp; + struct symbol *sym; + int i; + + while (!VTAILQ_EMPTY(&tl->membits)) { + mb = VTAILQ_FIRST(&tl->membits); + VTAILQ_REMOVE(&tl->membits, mb, list); + free(mb->ptr); + free(mb); + } + while (!VTAILQ_EMPTY(&tl->sources)) { + sp = VTAILQ_FIRST(&tl->sources); + VTAILQ_REMOVE(&tl->sources, sp, list); + vcc_destroy_source(sp); + } + + while (!VTAILQ_EMPTY(&tl->symbols)) { + sym = VTAILQ_FIRST(&tl->symbols); + VTAILQ_REMOVE(&tl->symbols, sym, list); + FREE_OBJ(sym); + } + + VSB_delete(tl->fh); + VSB_delete(tl->fc); + VSB_delete(tl->fi); + VSB_delete(tl->ff); + for (i = 0; i < VCL_MET_MAX; i++) + VSB_delete(tl->fm[i]); + + free(tl); + return (ret); +} + +/*-------------------------------------------------------------------- + * Compile the VCL code from the given source and return the C-source + */ + +static char * +vcc_CompileSource(const struct vcc *tl0, struct vsb *sb, struct source *sp) +{ + struct vcc *tl; + struct symbol *sym; + const struct var *v; + char *of; + int i; + + tl = vcc_NewVcc(tl0); + tl->sb = sb; + + vcc_Expr_Init(tl); + + for (v = tl->vars; v->name != NULL; v++) { + if (v->fmt == HEADER) { + sym = VCC_AddSymbolStr(tl, v->name, SYM_WILDCARD); + sym->wildcard = vcc_Var_Wildcard; + } else { + sym = VCC_AddSymbolStr(tl, v->name, SYM_VAR); + } + sym->var = v; + sym->fmt = v->fmt; + sym->eval = vcc_Eval_Var; + sym->r_methods = v->r_methods; + } + + sym = VCC_AddSymbolStr(tl, "storage.", SYM_WILDCARD); + sym->wildcard = vcc_Stv_Wildcard; + + vcl_output_lang_h(tl->fh); + Fh(tl, 0, "\n/* ---===### VCC generated below here ###===---*/\n"); + Fh(tl, 0, "\nextern const struct VCL_conf VCL_conf;\n"); + + /* Macro for accessing directors */ + Fh(tl, 0, "#define VGCDIR(n) VCL_conf.director[VGC_backend_##n]\n"); + + Fh(tl, 0, "#define __match_proto__(xxx) /*lint -e{818} */\n"); + + /* Register and lex the main source */ + VTAILQ_INSERT_TAIL(&tl->sources, sp, list); + sp->idx = tl->nsources++; + vcc_Lexer(tl, sp); + if (tl->err) + return (vcc_DestroyTokenList(tl, NULL)); + + /* Register and lex the default VCL */ + sp = vcc_new_source(tl->default_vcl, NULL, "Default"); + assert(sp != NULL); + VTAILQ_INSERT_TAIL(&tl->sources, sp, list); + sp->idx = tl->nsources++; + vcc_Lexer(tl, sp); + if (tl->err) + return (vcc_DestroyTokenList(tl, NULL)); + + /* Add "END OF INPUT" token */ + vcc_AddToken(tl, EOI, sp->e, sp->e); + if (tl->err) + return (vcc_DestroyTokenList(tl, NULL)); + + /* Expand and lex any includes in the token string */ + vcc_resolve_includes(tl); + if (tl->err) + return (vcc_DestroyTokenList(tl, NULL)); + + /* Parse the token string */ + tl->t = VTAILQ_FIRST(&tl->tokens); + vcc_Parse(tl); + if (tl->err) + return (vcc_DestroyTokenList(tl, NULL)); + + /* Check if we have any backends at all */ + if (tl->ndirector == 1) { + VSB_printf(tl->sb, + "No backends or directors found in VCL program, " + "at least one is necessary.\n"); + tl->err = 1; + return (vcc_DestroyTokenList(tl, NULL)); + } + + /* Configure the default director */ + Fi(tl, 0, "\tVCL_conf.director[0] = VCL_conf.director[%d];\n", + tl->defaultdir); + vcc_AddRef(tl, tl->t_defaultdir, SYM_BACKEND); + + /* Check for orphans */ + if (vcc_CheckReferences(tl)) + return (vcc_DestroyTokenList(tl, NULL)); + + /* Check that all action returns are legal */ + if (vcc_CheckAction(tl) || tl->err) + return (vcc_DestroyTokenList(tl, NULL)); + + /* Check that all variable uses are legal */ + if (vcc_CheckUses(tl) || tl->err) + return (vcc_DestroyTokenList(tl, NULL)); + + /* Emit method functions */ + for (i = 0; i < VCL_MET_MAX; i++) { + Fc(tl, 1, "\nstatic int __match_proto__(vcl_func_f)\n"); + Fc(tl, 1, + "VGC_function_%s(const struct vrt_ctx *ctx)\n", + method_tab[i].name); + AZ(VSB_finish(tl->fm[i])); + Fc(tl, 1, "{\n"); + Fc(tl, 1, "%s", VSB_data(tl->fm[i])); + Fc(tl, 1, "}\n"); + } + + LocTable(tl); + + EmitInitFunc(tl); + + EmitFiniFunc(tl); + + EmitStruct(tl); + + /* Combine it all in the fh vsb */ + AZ(VSB_finish(tl->fc)); + VSB_cat(tl->fh, VSB_data(tl->fc)); + AZ(VSB_finish(tl->fh)); + + of = strdup(VSB_data(tl->fh)); + AN(of); + + /* done */ + return (vcc_DestroyTokenList(tl, of)); +} + +/*-------------------------------------------------------------------- + * Compile the VCL code in the argument. Error messages, if any are + * formatted into the vsb. + */ + +char * +VCC_Compile(const struct vcc *tl, struct vsb *sb, const char *b) +{ + struct source *sp; + char *r; + + sp = vcc_new_source(b, NULL, "input"); + if (sp == NULL) + return (NULL); + r = vcc_CompileSource(tl, sb, sp); + return (r); +} + +/*-------------------------------------------------------------------- + * Allocate a compiler instance + */ + +struct vcc * +VCC_New(void) +{ + struct vcc *tl; + + tl = vcc_NewVcc(NULL); + + tl->vars = vcc_vars; + + return (tl); +} + +/*-------------------------------------------------------------------- + * Configure default VCL source code + */ + +void +VCC_Default_VCL(struct vcc *tl, const char *str) +{ + + CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); + REPLACE(tl->default_vcl, str); +} + +/*-------------------------------------------------------------------- + * Configure default VCL source directory + */ + +void +VCC_VCL_dir(struct vcc *tl, const char *str) +{ + + CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); + REPLACE(tl->vcl_dir, str); +} + +/*-------------------------------------------------------------------- + * Configure default VMOD directory + */ + +void +VCC_VMOD_dir(struct vcc *tl, const char *str) +{ + + CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); + REPLACE(tl->vmod_dir, str); +} + +/*-------------------------------------------------------------------- + * Configure settings + */ + +void +VCC_Err_Unref(struct vcc *tl, unsigned u) +{ + + CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); + tl->err_unref = u; +} + +void +VCC_Allow_InlineC(struct vcc *tl, unsigned u) +{ + + CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); + tl->allow_inline_c = u; +} + +void +VCC_Unsafe_Path(struct vcc *tl, unsigned u) +{ + + CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); + tl->unsafe_path = u; +} diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h new file mode 100644 index 0000000..b0983cc --- /dev/null +++ b/lib/libvcc/vcc_compile.h @@ -0,0 +1,351 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include + +#include +#include +#include + +#include "miniobj.h" +#include "vas.h" +#include "vcl.h" +#include "vdef.h" +#include "vqueue.h" +#include "vsb.h" + + +#include "vcc_token_defs.h" + +#ifndef NULL +#define NULL ((void*)0) +#endif + +struct vsb; +struct token; +struct sockaddr_storage; + +#define isident1(c) (isalpha(c)) +#define isident(c) (isalpha(c) || isdigit(c) || (c) == '_' || (c) == '-') +#define isvar(c) (isident(c) || (c) == '.') +int vcc_isCid(const struct token *t); +unsigned vcl_fixed_token(const char *p, const char **q); +extern const char * const vcl_tnames[256]; +void vcl_output_lang_h(struct vsb *sb); + +#define PF(t) (int)((t)->e - (t)->b), (t)->b + +#define INDENT 2 + +struct acl_e; +struct proc; +struct expr; +struct vcc; +struct symbol; + +enum var_type { +#define VCC_TYPE(foo) foo, +#include "tbl/vcc_types.h" +#undef VCC_TYPE +}; + +struct membit { + VTAILQ_ENTRY(membit) list; + void *ptr; +}; + +struct source { + VTAILQ_ENTRY(source) list; + char *name; + const char *b; + const char *e; + unsigned idx; + char *freeit; +}; + +struct token { + unsigned tok; + const char *b; + const char *e; + struct source *src; + VTAILQ_ENTRY(token) list; + unsigned cnt; + char *dec; +}; + +enum symkind { +#define VCC_SYMB(uu, ll) SYM_##uu, +#include "tbl/symbol_kind.h" +#undef VCC_SYMB +}; + +typedef void sym_expr_t(struct vcc *tl, struct expr **, + const struct symbol *sym); +typedef struct symbol *sym_wildcard_t(struct vcc *tl, const struct token *t, + const struct symbol *sym); + +struct symbol { + unsigned magic; +#define SYMBOL_MAGIC 0x3368c9fb + VTAILQ_ENTRY(symbol) list; + + char *name; + unsigned nlen; + sym_wildcard_t *wildcard; + enum symkind kind; + + const struct token *def_b, *def_e; + + enum var_type fmt; + + sym_expr_t *eval; + void *eval_priv; + + /* xref.c */ + struct proc *proc; + unsigned nref, ndef; + + /* SYM_PROC, SYM_FUNC */ + const char *cfunc; + const char *extra; + const char *args; + + /* SYM_VAR */ + const struct var *var; + unsigned r_methods; +}; + +VTAILQ_HEAD(tokenhead, token); + +struct vcc { + unsigned magic; +#define VCC_MAGIC 0x24ad719d + + /* Parameter/Template section */ + char *default_vcl; + char *vcl_dir; + char *vmod_dir; + + const struct var *vars; + VTAILQ_HEAD(, symbol) symbols; + + /* Instance section */ + struct tokenhead tokens; + VTAILQ_HEAD(, source) sources; + VTAILQ_HEAD(, membit) membits; + unsigned nsources; + struct source *src; + struct token *t; + int indent; + int hindent; + int iindent; + int findent; + unsigned cnt; + + struct vsb *fc; /* C-code */ + struct vsb *fh; /* H-code (before C-code) */ + struct vsb *fi; /* Init func code */ + struct vsb *fd; /* Object destructors */ + struct vsb *ff; /* Finish func code */ + struct vsb *fb; /* Body of current sub + * NULL otherwise + */ + struct vsb *fm[VCL_MET_MAX]; /* Method bodies */ + struct vsb *sb; + int err; + int ndirector; + struct proc *curproc; + struct proc *mprocs[VCL_MET_MAX]; + + VTAILQ_HEAD(, acl_e) acl; + + int nprobe; + + int defaultdir; + struct token *t_defaultdir; + + unsigned unique; + unsigned nvmodpriv; + + unsigned err_unref; + unsigned allow_inline_c; + unsigned unsafe_path; +}; + +struct var { + const char *name; + enum var_type fmt; + unsigned len; + const char *rname; + unsigned r_methods; + const char *lname; + unsigned w_methods; +}; + +struct method { + const char *name; + unsigned ret_bitmap; + unsigned bitval; +}; + +/*--------------------------------------------------------------------*/ + +/* vcc_acl.c */ + +void vcc_Acl(struct vcc *tl); +void vcc_Acl_Hack(struct vcc *tl, char *b); + +/* vcc_action.c */ +int vcc_ParseAction(struct vcc *tl); + +/* vcc_backend.c */ +#define MAX_BACKEND_NAME 64 +struct fld_spec; + +void vcc_ParseProbe(struct vcc *tl); +void vcc_ParseBackend(struct vcc *tl); +struct fld_spec * vcc_FldSpec(struct vcc *tl, const char *first, ...); +void vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs); +void vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs); + +/* vcc_compile.c */ +extern struct method method_tab[]; +/* + * H -> Header, before the C code + * C -> C-code + * B -> Body of function, ends up in C once function is completed + * I -> Initializer function + * F -> Finish function + */ +void Fh(const struct vcc *tl, int indent, const char *fmt, ...) + __printflike(3, 4); +void Fc(const struct vcc *tl, int indent, const char *fmt, ...) + __printflike(3, 4); +void Fb(const struct vcc *tl, int indent, const char *fmt, ...) + __printflike(3, 4); +void Fi(const struct vcc *tl, int indent, const char *fmt, ...) + __printflike(3, 4); +void Ff(const struct vcc *tl, int indent, const char *fmt, ...) + __printflike(3, 4); +void Fd(const struct vcc *tl, int indent, const char *fmt, ...) + __printflike(3, 4); +void EncToken(struct vsb *sb, const struct token *t); +int IsMethod(const struct token *t); +void *TlAlloc(struct vcc *tl, unsigned len); +char *TlDup(struct vcc *tl, const char *s); +char *TlDupTok(struct vcc *tl, const struct token *tok); + +void EncString(struct vsb *sb, const char *b, const char *e, int mode); + +/* vcc_expr.c */ +void vcc_Duration(struct vcc *tl, double *); +unsigned vcc_UintVal(struct vcc *tl); +void vcc_Expr(struct vcc *tl, enum var_type typ); +void vcc_Expr_Call(struct vcc *tl, const struct symbol *sym); +void vcc_Expr_Init(struct vcc *tl); +sym_expr_t vcc_Eval_Var; +sym_expr_t vcc_Eval_SymFunc; +void vcc_Eval_Func(struct vcc *tl, const char *cfunc, const char *extra, + const char *name, const char *args); +sym_expr_t vcc_Eval_Backend; + +/* vcc_obj.c */ +extern const struct var vcc_vars[]; + +/* vcc_parse.c */ +void vcc_Parse(struct vcc *tl); + +/* vcc_storage.c */ +sym_wildcard_t vcc_Stv_Wildcard; + +/* vcc_utils.c */ +const char *vcc_regexp(struct vcc *tl); +void Resolve_Sockaddr(struct vcc *tl, const char *host, const char *port, \ + const char **ipv4, const char **ipv4_ascii, const char **ipv6, \ + const char **ipv6_ascii, const char **p_ascii, int maxips, + const struct token *t_err, const char *errid); + +/* vcc_symb.c */ +struct symbol *VCC_AddSymbolStr(struct vcc *tl, const char *name, enum symkind); +struct symbol *VCC_AddSymbolTok(struct vcc *tl, const struct token *t, + enum symkind kind); +struct symbol *VCC_GetSymbolTok(struct vcc *tl, const struct token *tok, + enum symkind); +struct symbol *VCC_FindSymbol(struct vcc *tl, + const struct token *t, enum symkind kind); +const char * VCC_SymKind(struct vcc *tl, const struct symbol *s); +typedef void symwalk_f(struct vcc *tl, const struct symbol *s); +void VCC_WalkSymbols(struct vcc *tl, symwalk_f *func, enum symkind kind); + +/* vcc_token.c */ +void vcc_Coord(const struct vcc *tl, struct vsb *vsb, + const struct token *t); +void vcc_ErrToken(const struct vcc *tl, const struct token *t); +void vcc_ErrWhere(struct vcc *, const struct token *); +void vcc_ErrWhere2(struct vcc *, const struct token *, const struct token *); + +void vcc__Expect(struct vcc *tl, unsigned tok, unsigned line); +int vcc_IdIs(const struct token *t, const char *p); +void vcc_ExpectCid(struct vcc *tl); +void vcc_Lexer(struct vcc *tl, struct source *sp); +void vcc_NextToken(struct vcc *tl); +void vcc__ErrInternal(struct vcc *tl, const char *func, + unsigned line); +void vcc_AddToken(struct vcc *tl, unsigned tok, const char *b, + const char *e); + +/* vcc_var.c */ +sym_wildcard_t vcc_Var_Wildcard; +const struct var *vcc_FindVar(struct vcc *tl, const struct token *t, + int wr_access, const char *use); + +/* vcc_vmod.c */ +void vcc_ParseImport(struct vcc *tl); + +/* vcc_xref.c */ +int vcc_AddDef(struct vcc *tl, const struct token *t, enum symkind type); +void vcc_AddRef(struct vcc *tl, const struct token *t, enum symkind type); +int vcc_CheckReferences(struct vcc *tl); + +void vcc_AddCall(struct vcc *tl, struct token *t); +struct proc *vcc_AddProc(struct vcc *tl, struct token *t); +void vcc_ProcAction(struct proc *p, unsigned action, struct token *t); +int vcc_CheckAction(struct vcc *tl); +void vcc_AddUses(struct vcc *tl, const struct token *t, unsigned mask, + const char *use); +int vcc_CheckUses(struct vcc *tl); + +#define ERRCHK(tl) do { if ((tl)->err) return; } while (0) +#define ErrInternal(tl) vcc__ErrInternal(tl, __func__, __LINE__) +#define Expect(a, b) vcc__Expect(a, b, __LINE__) +#define ExpectErr(a, b) \ + do { vcc__Expect(a, b, __LINE__); ERRCHK(a);} while (0) +#define SkipToken(a, b) \ + do { vcc__Expect(a, b, __LINE__); ERRCHK(a); vcc_NextToken(a); } while (0) diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c new file mode 100644 index 0000000..164a8d6 --- /dev/null +++ b/lib/libvcc/vcc_expr.c @@ -0,0 +1,1257 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2011 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * XXX: add VRT_count()'s + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "vcc_compile.h" + +static const char * +vcc_Type(enum var_type fmt) +{ + switch(fmt) { +#define VCC_TYPE(a) case a: return(#a); +#include "tbl/vcc_types.h" +#undef VCC_TYPE + default: + assert("Unknown Type"); + return(NULL); + } +} + +/*-------------------------------------------------------------------- + * Recognize and convert units of time, return seconds. + */ + +static double +vcc_TimeUnit(struct vcc *tl) +{ + double sc = 1.0; + + assert(tl->t->tok == ID); + if (vcc_IdIs(tl->t, "ms")) + sc = 1e-3; + else if (vcc_IdIs(tl->t, "s")) + sc = 1.0; + else if (vcc_IdIs(tl->t, "m")) + sc = 60.0; + else if (vcc_IdIs(tl->t, "h")) + sc = 60.0 * 60.0; + else if (vcc_IdIs(tl->t, "d")) + sc = 60.0 * 60.0 * 24.0; + else if (vcc_IdIs(tl->t, "w")) + sc = 60.0 * 60.0 * 24.0 * 7.0; + else { + VSB_printf(tl->sb, "Unknown time unit "); + vcc_ErrToken(tl, tl->t); + VSB_printf(tl->sb, ". Legal are 's', 'm', 'h' and 'd'\n"); + vcc_ErrWhere(tl, tl->t); + return (1.0); + } + vcc_NextToken(tl); + return (sc); +} + +/*-------------------------------------------------------------------- + * Recognize and convert { CNUM } to unsigned value + * The tokenizer made sure we only get digits. + */ + +unsigned +vcc_UintVal(struct vcc *tl) +{ + unsigned d = 0; + const char *p; + + Expect(tl, CNUM); + for (p = tl->t->b; p < tl->t->e; p++) { + d *= 10; + d += *p - '0'; + } + vcc_NextToken(tl); + return (d); +} + +/*-------------------------------------------------------------------- + * Recognize and convert { CNUM [ '.' [ CNUM ] ] } to double value + * The tokenizer made sure we only get digits and a '.' + */ + +static void +vcc_NumVal(struct vcc *tl, double *d, int *frac) +{ + double e = 0.1; + const char *p; + + *frac = 0; + *d = 0.0; + Expect(tl, CNUM); + if (tl->err) { + *d = NAN; + return; + } + for (p = tl->t->b; p < tl->t->e; p++) { + *d *= 10; + *d += *p - '0'; + } + vcc_NextToken(tl); + if (tl->t->tok != '.') + return; + *frac = 1; + vcc_NextToken(tl); + if (tl->t->tok != CNUM) + return; + for (p = tl->t->b; p < tl->t->e; p++) { + *d += (*p - '0') * e; + e *= 0.1; + } + vcc_NextToken(tl); +} + +static double +vcc_DoubleVal(struct vcc *tl) +{ + double d; + int i; + + vcc_NumVal(tl, &d, &i); + return (d); +} + +/*--------------------------------------------------------------------*/ + +void +vcc_Duration(struct vcc *tl, double *d) +{ + double v, sc; + + v = vcc_DoubleVal(tl); + ERRCHK(tl); + ExpectErr(tl, ID); + sc = vcc_TimeUnit(tl); + *d = v * sc; +} + +/*--------------------------------------------------------------------*/ + +static void +vcc_ByteVal(struct vcc *tl, double *d) +{ + double v, sc; + + v = vcc_DoubleVal(tl); + ERRCHK(tl); + if (tl->t->tok != ID) { + VSB_printf(tl->sb, "Expected BYTES unit (B, KB, MB...) got "); + vcc_ErrToken(tl, tl->t); + VSB_printf(tl->sb, "\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + if (vcc_IdIs(tl->t, "B")) + sc = 1.; + else if (vcc_IdIs(tl->t, "KB")) + sc = 1024.; + else if (vcc_IdIs(tl->t, "MB")) + sc = 1024. * 1024.; + else if (vcc_IdIs(tl->t, "GB")) + sc = 1024. * 1024. * 1024.; + else if (vcc_IdIs(tl->t, "TB")) + sc = 1024. * 1024. * 1024. * 1024.; + else { + VSB_printf(tl->sb, "Unknown BYTES unit "); + vcc_ErrToken(tl, tl->t); + VSB_printf(tl->sb, + ". Legal are 'B', 'KB', 'MB', 'GB' and 'TB'\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + vcc_NextToken(tl); + *d = v * sc; +} + +/*-------------------------------------------------------------------- + * Facility for carrying expressions around and do text-processing on + * them. + */ + +struct expr { + unsigned magic; +#define EXPR_MAGIC 0x38c794ab + enum var_type fmt; + struct vsb *vsb; + uint8_t constant; +#define EXPR_VAR (1<<0) +#define EXPR_CONST (1<<1) +#define EXPR_STR_CONST (1<<2) + struct token *t1, *t2; +}; + +static inline int +vcc_isconst(const struct expr *e) +{ + AN(e->constant); + return (e->constant & EXPR_CONST); +} + +static void vcc_expr0(struct vcc *tl, struct expr **e, enum var_type fmt); + +static struct expr * +vcc_new_expr(void) +{ + struct expr *e; + + /* XXX: use TlAlloc() ? */ + ALLOC_OBJ(e, EXPR_MAGIC); + AN(e); + e->vsb = VSB_new_auto(); + e->fmt = VOID; + e->constant = EXPR_VAR; + return (e); +} + +static struct expr * +vcc_mk_expr(enum var_type fmt, const char *str, ...) + __printflike(2, 3); + +static struct expr * +vcc_mk_expr(enum var_type fmt, const char *str, ...) +{ + va_list ap; + struct expr *e; + + e = vcc_new_expr(); + e->fmt = fmt; + va_start(ap, str); + VSB_vprintf(e->vsb, str, ap); + va_end(ap); + AZ(VSB_finish(e->vsb)); + return (e); +} + +static void +vcc_delete_expr(struct expr *e) +{ + if (e == NULL) + return; + CHECK_OBJ_NOTNULL(e, EXPR_MAGIC); + VSB_delete(e->vsb); + FREE_OBJ(e); +} +/*-------------------------------------------------------------------- + * We want to get the indentation right in the emitted C code so we have + * to represent it symbolically until we are ready to render. + * + * Many of the operations have very schematic output syntaxes, so we + * use the same facility to simplify the text-processing of emitting + * a given operation on two subexpressions. + * + * We use '\v' as the magic escape character. + * \v1 insert subexpression 1 + * \v2 insert subexpression 2 + * \v+ increase indentation + * \v- increase indentation + * anything else is literal + * + * When editing, we check if any of the subexpressions contain a newline + * and issue it as an indented block of so. + * + * XXX: check line lengths in edit, should pass indent in for this + */ + +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); +} + +/*-------------------------------------------------------------------- + * Expand finished expression into C-source code + */ + +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: + WRONG("Illegal format in VCC expression"); + } + p++; + } +} + +/*-------------------------------------------------------------------- + */ + +static enum var_type +vcc_arg_type(const char **p) +{ + +#define VCC_TYPE(a) if (!strcmp(#a, *p)) { *p += strlen(#a) + 1; return (a);} +#include "tbl/vcc_types.h" +#undef VCC_TYPE + return (VOID); +} + +/*-------------------------------------------------------------------- + */ + +static void +vcc_expr_tostring(struct expr **e, enum var_type fmt) +{ + const char *p; + uint8_t constant = EXPR_VAR; + + CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC); + AN(fmt == STRING || fmt == STRING_LIST); + + p = NULL; + switch((*e)->fmt) { + case BACKEND: p = "VRT_BACKEND_string(\v1)"; break; + case BOOL: p = "VRT_BOOL_string(\v1)"; break; + case DURATION: p = "VRT_REAL_string(ctx, \v1)"; break; + /* XXX: should DURATION insist on "s" suffix ? */ + case INT: + if (vcc_isconst(*e)) { + p = "\"\v1\""; + constant = EXPR_CONST; + } else { + p = "VRT_INT_string(ctx, \v1)"; + } + break; + case IP: p = "VRT_IP_string(ctx, \v1)"; break; + case BYTES: p = "VRT_REAL_string(ctx, \v1)"; break; /* XXX */ + case REAL: p = "VRT_REAL_string(ctx, \v1)"; break; + case TIME: p = "VRT_TIME_string(ctx, \v1)"; break; + case HEADER: p = "VRT_GetHdr(ctx, \v1)"; break; + case ENUM: + case STRING: + case STRING_LIST: + break; + default: + INCOMPL(); + break; + } + if (p != NULL) { + *e = vcc_expr_edit(fmt, p, *e, NULL); + (*e)->constant = constant; + } +} + +/*-------------------------------------------------------------------- + */ + +static void +vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym) +{ + struct expr *e2; + int all = sym->eval_priv == NULL ? 0 : 1; + const char *p; + char buf[128]; + + vcc_delete_expr(*e); + SkipToken(tl, ID); + SkipToken(tl, '('); + + vcc_expr0(tl, &e2, STRING); + if (e2 == NULL) + return; + if (e2->fmt != STRING) + vcc_expr_tostring(&e2, STRING); + + SkipToken(tl, ','); + ExpectErr(tl, CSTR); + p = vcc_regexp(tl); + vcc_NextToken(tl); + + bprintf(buf, "VRT_regsub(ctx, %d,\v+\n\v1,\n%s", all, p); + *e = vcc_expr_edit(STRING, buf, e2, *e); + + SkipToken(tl, ','); + vcc_expr0(tl, &e2, STRING); + if (e2 == NULL) + return; + if (e2->fmt != STRING) + vcc_expr_tostring(&e2, STRING); + *e = vcc_expr_edit(STRING, "\v1,\n\v2)\v-", *e, e2); + SkipToken(tl, ')'); +} + +/*-------------------------------------------------------------------- + */ + +static void +vcc_Eval_BoolConst(struct vcc *tl, struct expr **e, const struct symbol *sym) +{ + + vcc_NextToken(tl); + *e = vcc_mk_expr(BOOL, "(0==%d)", sym->eval_priv == NULL ? 1 : 0); + (*e)->constant = EXPR_CONST; +} + +/*-------------------------------------------------------------------- + */ + +void +vcc_Eval_Backend(struct vcc *tl, struct expr **e, const struct symbol *sym) +{ + + assert(sym->kind == SYM_BACKEND); + + vcc_ExpectCid(tl); + vcc_AddRef(tl, tl->t, SYM_BACKEND); + *e = vcc_mk_expr(BACKEND, "VGCDIR(_%.*s)", PF(tl->t)); + (*e)->constant = EXPR_VAR; /* XXX ? */ + vcc_NextToken(tl); +} + +/*-------------------------------------------------------------------- + */ +void +vcc_Eval_Var(struct vcc *tl, struct expr **e, const struct symbol *sym) +{ + const struct var *vp; + + assert(sym->kind == SYM_VAR); + vcc_AddUses(tl, tl->t, sym->r_methods, "Not available"); + vp = vcc_FindVar(tl, tl->t, 0, "cannot be read"); + ERRCHK(tl); + assert(vp != NULL); + *e = vcc_mk_expr(vp->fmt, "%s", vp->rname); + vcc_NextToken(tl); +} + +/*-------------------------------------------------------------------- + */ + +static void +vcc_func(struct vcc *tl, struct expr **e, const char *cfunc, + const char *extra, const char *name, const char *args) +{ + const char *p, *r; + struct expr *e1, *e2; + enum var_type fmt; + char buf[32]; + + AN(cfunc); + AN(args); + AN(name); + SkipToken(tl, '('); + p = args; + if (extra == NULL) + extra = ""; + e2 = vcc_mk_expr(vcc_arg_type(&p), "%s(ctx%s\v+", cfunc, extra); + while (*p != '\0') { + e1 = NULL; + fmt = vcc_arg_type(&p); + if (fmt == VOID && !strcmp(p, "PRIV_VCL")) { + r = strchr(name, '.'); + AN(r); + e1 = vcc_mk_expr(VOID, "&vmod_priv_%.*s", + (int) (r - name), name); + p += strlen(p) + 1; + } else if (fmt == VOID && !strcmp(p, "PRIV_CALL")) { + bprintf(buf, "vmod_priv_%u", tl->nvmodpriv++); + Fh(tl, 0, "struct vmod_priv %s;\n", buf); + e1 = vcc_mk_expr(VOID, "&%s", buf); + p += strlen(p) + 1; + } else if (fmt == ENUM) { + ExpectErr(tl, ID); + ERRCHK(tl); + r = p; + do { + if (vcc_IdIs(tl->t, p)) + break; + p += strlen(p) + 1; + } while (*p != '\0'); + if (*p == '\0') { + VSB_printf(tl->sb, "Wrong enum value."); + VSB_printf(tl->sb, " Expected one of:\n"); + do { + VSB_printf(tl->sb, "\t%s\n", r); + r += strlen(r) + 1; + } while (*r != '\0'); + vcc_ErrWhere(tl, tl->t); + return; + } + e1 = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t)); + while (*p != '\0') + p += strlen(p) + 1; + p++; + SkipToken(tl, ID); + if (*p != '\0') /*lint !e448 */ + SkipToken(tl, ','); + } else { + vcc_expr0(tl, &e1, fmt); + ERRCHK(tl); + if (e1->fmt != fmt) { + VSB_printf(tl->sb, "Wrong argument type."); + VSB_printf(tl->sb, " Expected %s.", + vcc_Type(fmt)); + VSB_printf(tl->sb, " Got %s.\n", + vcc_Type(e1->fmt)); + vcc_ErrWhere2(tl, e1->t1, tl->t); + return; + } + assert(e1->fmt == fmt); + if (e1->fmt == STRING_LIST) { + e1 = vcc_expr_edit(STRING_LIST, + "\v+\n\v1,\nvrt_magic_string_end\v-", + e1, NULL); + } + if (*p != '\0') + SkipToken(tl, ','); + } + e2 = vcc_expr_edit(e2->fmt, "\v1,\n\v2", e2, e1); + } + SkipToken(tl, ')'); + e2 = vcc_expr_edit(e2->fmt, "\v1\n)\v-", e2, NULL); + *e = e2; +} + +/*-------------------------------------------------------------------- + */ + +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_Eval_SymFunc(struct vcc *tl, struct expr **e, const struct symbol *sym) +{ + + assert(sym->kind == SYM_FUNC || sym->kind == SYM_PROC); + AN(sym->cfunc); + AN(sym->name); + AN(sym->args); + SkipToken(tl, ID); + vcc_func(tl, e, sym->cfunc, sym->extra, sym->name, sym->args); +} + +/*-------------------------------------------------------------------- + * SYNTAX: + * Expr4: + * '(' Expr0 ')' + * CNUM + * CSTR + */ + +static void +vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt) +{ + struct expr *e1, *e2; + const char *ip; + const struct symbol *sym; + double d; + + *e = NULL; + if (tl->t->tok == '(') { + SkipToken(tl, '('); + vcc_expr0(tl, &e2, fmt); + ERRCHK(tl); + SkipToken(tl, ')'); + *e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL); + return; + } + switch(tl->t->tok) { + case ID: + /* + * XXX: what if var and func/proc had same name ? + * XXX: look for SYM_VAR first for consistency ? + */ + sym = VCC_FindSymbol(tl, tl->t, SYM_NONE); + if (sym == NULL || sym->eval == NULL) { + VSB_printf(tl->sb, "Symbol not found: "); + vcc_ErrToken(tl, tl->t); + VSB_printf(tl->sb, " (expected type %s):\n", + vcc_Type(fmt)); + vcc_ErrWhere(tl, tl->t); + return; + } + AN(sym); + switch(sym->kind) { + case SYM_VAR: + case SYM_FUNC: + case SYM_BACKEND: + AN(sym->eval); + AZ(*e); + sym->eval(tl, e, sym); + return; + default: + break; + } + VSB_printf(tl->sb, + "Symbol type (%s) can not be used in expression.\n", + VCC_SymKind(tl, sym)); + vcc_ErrWhere(tl, tl->t); + return; + case CSTR: + assert(fmt != VOID); + if (fmt == IP) { + Resolve_Sockaddr(tl, tl->t->dec, "80", + &ip, NULL, &ip, NULL, NULL, 1, + tl->t, "IP constant"); + ERRCHK(tl); + e1 = vcc_mk_expr(IP, "%s", ip); + ERRCHK(tl); + } else { + e1 = vcc_new_expr(); + EncToken(e1->vsb, tl->t); + e1->fmt = STRING; + AZ(VSB_finish(e1->vsb)); + } + e1->t1 = tl->t; + e1->constant = EXPR_CONST; + vcc_NextToken(tl); + *e = e1; + break; + case CNUM: + /* + * XXX: %g may not have enough decimals by default + * XXX: but %a is ugly, isn't it ? + */ + assert(fmt != VOID); + if (fmt == DURATION) { + vcc_Duration(tl, &d); + ERRCHK(tl); + e1 = vcc_mk_expr(DURATION, "%g", d); + } else if (fmt == BYTES) { + vcc_ByteVal(tl, &d); + ERRCHK(tl); + e1 = vcc_mk_expr(BYTES, "%.1f", d); + ERRCHK(tl); + } else if (fmt == REAL) { + e1 = vcc_mk_expr(REAL, "%g", vcc_DoubleVal(tl)); + ERRCHK(tl); + } else { + e1 = vcc_mk_expr(INT, "%.*s", PF(tl->t)); + vcc_NextToken(tl); + } + e1->constant = EXPR_CONST; + *e = e1; + break; + default: + VSB_printf(tl->sb, "Unknown token "); + vcc_ErrToken(tl, tl->t); + VSB_printf(tl->sb, " when looking for %s\n\n", vcc_Type(fmt)); + vcc_ErrWhere(tl, tl->t); + break; + } +} + +/*-------------------------------------------------------------------- + * SYNTAX: + * Expr3: + * Expr4 { {'*'|'/'} Expr4 } * + */ + +static void +vcc_expr_mul(struct vcc *tl, struct expr **e, enum var_type fmt) +{ + struct expr *e2; + enum var_type f2, f3; + struct token *tk; + + *e = NULL; + vcc_expr4(tl, e, fmt); + ERRCHK(tl); + f3 = f2 = (*e)->fmt; + + switch(f2) { + case INT: f2 = INT; break; + case DURATION: f2 = REAL; break; + case BYTES: f2 = REAL; break; + default: + if (tl->t->tok != '*' && tl->t->tok != '/') + return; + VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n", + PF(tl->t), vcc_Type(f2)); + vcc_ErrWhere(tl, tl->t); + return; + } + + while (tl->t->tok == '*' || tl->t->tok == '/') { + tk = tl->t; + vcc_NextToken(tl); + vcc_expr4(tl, &e2, f2); + ERRCHK(tl); + assert(e2->fmt == f2); + if (tk->tok == '*') + *e = vcc_expr_edit(f3, "(\v1*\v2)", *e, e2); + else + *e = vcc_expr_edit(f3, "(\v1/\v2)", *e, e2); + } +} + +/*-------------------------------------------------------------------- + * SYNTAX: + * ExprAdd: + * ExprMul { {'+'|'-'} ExprMul } * + * + * For reasons of memory allocation/copying and general performance, + * STRINGs in VCL are quite special. Addition/concatenation is split + * into it's own subfunction to encapsulate this. + */ + +static void +vcc_expr_string_add(struct vcc *tl, struct expr **e) +{ + struct expr *e2; + enum var_type f2; + + f2 = (*e)->fmt; + + while (tl->t->tok == '+') { + vcc_NextToken(tl); + vcc_expr_mul(tl, &e2, STRING); + ERRCHK(tl); + if (e2->fmt != STRING && e2->fmt != STRING_LIST) + vcc_expr_tostring(&e2, f2); + ERRCHK(tl); + assert(e2->fmt == STRING || e2->fmt == STRING_LIST); + + if (vcc_isconst(*e) && vcc_isconst(e2)) { + assert((*e)->fmt == STRING); + assert(e2->fmt == STRING); + *e = vcc_expr_edit(STRING, "\v1\n\v2", *e, e2); + (*e)->constant = EXPR_CONST; + } else if (((*e)->constant & EXPR_STR_CONST) && + vcc_isconst(e2)) { + assert((*e)->fmt == STRING_LIST); + assert(e2->fmt == STRING); + *e = vcc_expr_edit(STRING_LIST, "\v1\n\v2", *e, e2); + (*e)->constant = EXPR_VAR | EXPR_STR_CONST; + } else if (e2->fmt == STRING && vcc_isconst(e2)) { + *e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2); + (*e)->constant = EXPR_VAR | EXPR_STR_CONST; + } else { + *e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2); + (*e)->constant = EXPR_VAR; + } + } +} + +static void +vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt) +{ + struct expr *e2; + enum var_type f2; + struct token *tk; + + *e = NULL; + vcc_expr_mul(tl, e, fmt); + ERRCHK(tl); + f2 = (*e)->fmt; + + /* Unless we specifically ask for a HEADER, fold them to string here */ + if (fmt != HEADER && f2 == HEADER) { + vcc_expr_tostring(e, STRING); + f2 = (*e)->fmt; + assert(f2 == STRING); + } + + if (tl->t->tok != '+' && tl->t->tok != '-') + return; + + switch(f2) { + case STRING: + case STRING_LIST: + vcc_expr_string_add(tl, e); + return; + case INT: break; + case TIME: break; + case DURATION: break; + case BYTES: break; + default: + VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n", + PF(tl->t), vcc_Type(f2)); + vcc_ErrWhere(tl, tl->t); + return; + } + + while (tl->t->tok == '+' || tl->t->tok == '-') { + if (f2 == TIME) + f2 = DURATION; + tk = tl->t; + vcc_NextToken(tl); + vcc_expr_mul(tl, &e2, f2); + ERRCHK(tl); + if (tk->tok == '-' && (*e)->fmt == TIME && e2->fmt == TIME) { + /* OK */ + } else if ((*e)->fmt == TIME && e2->fmt == DURATION) { + f2 = TIME; + /* OK */ + } else if (tk->tok == '-' && + (*e)->fmt == BYTES && e2->fmt == BYTES) { + /* OK */ + } else if (e2->fmt != f2) { + VSB_printf(tl->sb, "%s %.*s %s not possible.\n", + vcc_Type((*e)->fmt), PF(tk), vcc_Type(e2->fmt)); + vcc_ErrWhere2(tl, tk, tl->t); + return; + } + if (tk->tok == '+') + *e = vcc_expr_edit(f2, "(\v1+\v2)", *e, e2); + else if (f2 == TIME && e2->fmt == TIME) + *e = vcc_expr_edit(DURATION, "(\v1-\v2)", *e, e2); + else + *e = vcc_expr_edit(f2, "(\v1-\v2)", *e, e2); + } +} + +/*-------------------------------------------------------------------- + * Fold the STRING types correctly + */ + +static void +vcc_expr_strfold(struct vcc *tl, struct expr **e, enum var_type fmt) +{ + + vcc_expr_add(tl, e, fmt); + ERRCHK(tl); + + if (fmt != STRING_LIST && (*e)->fmt == STRING_LIST) + *e = vcc_expr_edit(STRING, + "\v+VRT_CollectString(ctx,\n\v1,\nvrt_magic_string_end)\v-", + *e, NULL); + if (fmt == STRING_LIST && (*e)->fmt == STRING) + (*e)->fmt = STRING_LIST; +} + +/*-------------------------------------------------------------------- + * SYNTAX: + * ExprCmp: + * ExprAdd + * ExprAdd Relation ExprAdd + * ExprAdd(STRING) '~' CString + * ExprAdd(STRING) '!~' CString + * ExprAdd(IP) '~' IP + * ExprAdd(IP) '!~' IP + */ + +#define NUM_REL(typ) \ + {typ, T_EQ, "(\v1 == \v2)" }, \ + {typ, T_NEQ, "(\v1 != \v2)" }, \ + {typ, T_LEQ, "(\v1 <= \v2)" }, \ + {typ, T_GEQ, "(\v1 >= \v2)" }, \ + {typ, '<', "(\v1 < \v2)" }, \ + {typ, '>', "(\v1 > \v2)" } + +static const struct cmps { + enum var_type fmt; + unsigned token; + const char *emit; +} vcc_cmps[] = { + NUM_REL(INT), + NUM_REL(DURATION), + NUM_REL(BYTES), + NUM_REL(REAL), + + {STRING, T_EQ, "!VRT_strcmp(\v1, \v2)" }, + {STRING, T_NEQ, "VRT_strcmp(\v1, \v2)" }, + + {VOID, 0, NULL} +}; + +#undef NUM_REL + +static void +vcc_expr_cmp(struct vcc *tl, struct expr **e, enum var_type fmt) +{ + struct expr *e2; + const struct cmps *cp; + char buf[256]; + const char *re; + const char *not; + struct token *tk; + + *e = NULL; + + vcc_expr_strfold(tl, e, fmt); + ERRCHK(tl); + + if ((*e)->fmt == BOOL) + return; + + tk = tl->t; + for (cp = vcc_cmps; cp->fmt != VOID; cp++) + if ((*e)->fmt == cp->fmt && tl->t->tok == cp->token) + break; + if (cp->fmt != VOID) { + vcc_NextToken(tl); + vcc_expr_strfold(tl, &e2, (*e)->fmt); + ERRCHK(tl); + if (e2->fmt != (*e)->fmt) { /* XXX */ + VSB_printf(tl->sb, "Comparison of different types: "); + VSB_printf(tl->sb, "%s ", vcc_Type((*e)->fmt)); + vcc_ErrToken(tl, tk); + VSB_printf(tl->sb, " %s\n", vcc_Type(e2->fmt)); + vcc_ErrWhere(tl, tk); + return; + } + *e = vcc_expr_edit(BOOL, cp->emit, *e, e2); + return; + } + if ((*e)->fmt == STRING && + (tl->t->tok == '~' || tl->t->tok == T_NOMATCH)) { + not = tl->t->tok == '~' ? "" : "!"; + vcc_NextToken(tl); + ExpectErr(tl, CSTR); + re = vcc_regexp(tl); + ERRCHK(tl); + vcc_NextToken(tl); + bprintf(buf, "%sVRT_re_match(ctx, \v1, %s)", not, re); + *e = vcc_expr_edit(BOOL, buf, *e, NULL); + return; + } + if ((*e)->fmt == IP && + (tl->t->tok == '~' || tl->t->tok == T_NOMATCH)) { + not = tl->t->tok == '~' ? "" : "!"; + vcc_NextToken(tl); + ExpectErr(tl, ID); + vcc_AddRef(tl, tl->t, SYM_ACL); + bprintf(buf, "%smatch_acl_named_%.*s(ctx, \v1)", + not, PF(tl->t)); + vcc_NextToken(tl); + *e = vcc_expr_edit(BOOL, buf, *e, NULL); + return; + } + if ((*e)->fmt == IP && (tl->t->tok == T_EQ || tl->t->tok == T_NEQ)) { + vcc_Acl_Hack(tl, buf); + *e = vcc_expr_edit(BOOL, buf, *e, NULL); + return; + } + if ((*e)->fmt == BACKEND && + (tl->t->tok == T_EQ || tl->t->tok == T_NEQ)) { + vcc_NextToken(tl); + ExpectErr(tl, ID); + vcc_AddRef(tl, tl->t, SYM_BACKEND); + bprintf(buf, "(\v1 %.*s VGCDIR(_%.*s))", PF(tk), PF(tl->t)); + vcc_NextToken(tl); + *e = vcc_expr_edit(BOOL, buf, *e, NULL); + return; + } + switch (tl->t->tok) { + case T_EQ: + case T_NEQ: + case '<': + case T_LEQ: + case '>': + case T_GEQ: + case '~': + case T_NOMATCH: + VSB_printf(tl->sb, "Operator %.*s not possible on %s\n", + PF(tl->t), vcc_Type((*e)->fmt)); + vcc_ErrWhere(tl, tl->t); + return; + default: + break; + } + if (fmt == BOOL && (*e)->fmt == STRING) { + *e = vcc_expr_edit(BOOL, "(\v1 != 0)", *e, NULL); + return; + } +} + +/*-------------------------------------------------------------------- + * SYNTAX: + * ExprNot: + * '!' ExprCmp + */ + +static void +vcc_expr_not(struct vcc *tl, struct expr **e, enum var_type fmt) +{ + struct expr *e2; + struct token *tk; + + *e = NULL; + if (fmt != BOOL || tl->t->tok != '!') { + vcc_expr_cmp(tl, e, fmt); + return; + } + + vcc_NextToken(tl); + tk = tl->t; + vcc_expr_cmp(tl, &e2, fmt); + ERRCHK(tl); + if (e2->fmt == BOOL) { + *e = vcc_expr_edit(BOOL, "!(\v1)", e2, NULL); + return; + } + VSB_printf(tl->sb, "'!' must be followed by BOOL, found "); + VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt)); + vcc_ErrWhere2(tl, tk, tl->t); +} + +/*-------------------------------------------------------------------- + * SYNTAX: + * ExprCand: + * ExprNot { '&&' ExprNot } * + */ + +static void +vcc_expr_cand(struct vcc *tl, struct expr **e, enum var_type fmt) +{ + struct expr *e2; + struct token *tk; + + *e = NULL; + vcc_expr_not(tl, e, fmt); + ERRCHK(tl); + if ((*e)->fmt != BOOL || tl->t->tok != T_CAND) + return; + *e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL); + while (tl->t->tok == T_CAND) { + vcc_NextToken(tl); + tk = tl->t; + vcc_expr_not(tl, &e2, fmt); + ERRCHK(tl); + if (e2->fmt != BOOL) { + VSB_printf(tl->sb, + "'&&' must be followed by BOOL, found "); + VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt)); + vcc_ErrWhere2(tl, tk, tl->t); + return; + } + *e = vcc_expr_edit(BOOL, "\v1\v-\n&&\v+\n\v2", *e, e2); + } + *e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL); +} + +/*-------------------------------------------------------------------- + * SYNTAX: + * Expr0: + * ExprCand { '||' ExprCand } * + */ + +static void +vcc_expr0(struct vcc *tl, struct expr **e, enum var_type fmt) +{ + struct expr *e2; + struct token *tk; + + *e = NULL; + vcc_expr_cand(tl, e, fmt); + ERRCHK(tl); + if ((*e)->fmt != BOOL || tl->t->tok != T_COR) + return; + *e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL); + while (tl->t->tok == T_COR) { + vcc_NextToken(tl); + tk = tl->t; + vcc_expr_cand(tl, &e2, fmt); + ERRCHK(tl); + if (e2->fmt != BOOL) { + VSB_printf(tl->sb, + "'||' must be followed by BOOL, found "); + VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt)); + vcc_ErrWhere2(tl, tk, tl->t); + return; + } + *e = vcc_expr_edit(BOOL, "\v1\v-\n||\v+\n\v2", *e, e2); + } + *e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL); +} + +/*-------------------------------------------------------------------- + * This function parses and emits the C-code to evaluate an expression + * + * We know up front what kind of type we want the expression to be, + * and this function is the backstop if that doesn't succeed. + */ + +void +vcc_Expr(struct vcc *tl, enum var_type fmt) +{ + struct expr *e; + struct token *t1; + + assert(fmt != VOID); + + t1 = tl->t; + vcc_expr0(tl, &e, fmt); + ERRCHK(tl); + if (fmt == STRING || fmt == STRING_LIST) + vcc_expr_tostring(&e, fmt); + if (!tl->err && fmt != e->fmt) { + VSB_printf(tl->sb, "Expression has type %s, expected %s\n", + vcc_Type(e->fmt), vcc_Type(fmt)); + tl->err = 1; + } + if (!tl->err) { + if (e->fmt == STRING_LIST) { + e = vcc_expr_edit(STRING_LIST, + "\v+\n\v1,\nvrt_magic_string_end\v-", e, NULL); + } + vcc_expr_fmt(tl->fb, tl->indent, e); + VSB_putc(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_SymFunc(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 +vcc_Expr_Init(struct vcc *tl) +{ + struct symbol *sym; + + sym = VCC_AddSymbolStr(tl, "regsub", SYM_FUNC); + AN(sym); + sym->eval = vcc_Eval_Regsub; + sym->eval_priv = NULL; + + sym = VCC_AddSymbolStr(tl, "regsuball", SYM_FUNC); + AN(sym); + sym->eval = vcc_Eval_Regsub; + sym->eval_priv = sym; + + sym = VCC_AddSymbolStr(tl, "true", SYM_FUNC); + AN(sym); + sym->eval = vcc_Eval_BoolConst; + sym->eval_priv = sym; + + sym = VCC_AddSymbolStr(tl, "false", SYM_FUNC); + AN(sym); + sym->eval = vcc_Eval_BoolConst; + sym->eval_priv = NULL; +} diff --git a/lib/libvcc/vcc_parse.c b/lib/libvcc/vcc_parse.c new file mode 100644 index 0000000..ab562f5 --- /dev/null +++ b/lib/libvcc/vcc_parse.c @@ -0,0 +1,359 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include + +#include "vcc_compile.h" + +/*--------------------------------------------------------------------*/ + +static void vcc_Compound(struct vcc *tl); + +/*--------------------------------------------------------------------*/ + +#define L(tl, foo) do { \ + tl->indent += INDENT; \ + foo; \ + tl->indent -= INDENT; \ +} while (0) + +#define C(tl, sep) do { \ + Fb(tl, 1, "VRT_count(ctx, %u)%s\n", ++tl->cnt, sep); \ + tl->t->cnt = tl->cnt; \ +} while (0) + +/*-------------------------------------------------------------------- + * SYNTAX: + * Conditional: + * '(' Cond_0 ')' + */ + +static void +vcc_Conditional(struct vcc *tl) +{ + + SkipToken(tl, '('); + Fb(tl, 0, "(\n"); + L(tl, vcc_Expr(tl, BOOL)); + ERRCHK(tl); + Fb(tl, 1, ")\n"); + SkipToken(tl, ')'); +} + +/*-------------------------------------------------------------------- + * SYNTAX: + * IfStmt: + * 'if' Conditional Compound Branch1* Branch2 + * Branch1: + * 'elseif' Conditional Compound + * Branch2: + * 'else' Compound + * null + */ + +static void +vcc_IfStmt(struct vcc *tl) +{ + + SkipToken(tl, ID); + Fb(tl, 1, "if "); + vcc_Conditional(tl); + ERRCHK(tl); + L(tl, vcc_Compound(tl)); + ERRCHK(tl); + while (tl->t->tok == ID) { + if (vcc_IdIs(tl->t, "else")) { + vcc_NextToken(tl); + if (tl->t->tok == '{') { + Fb(tl, 1, "else\n"); + L(tl, vcc_Compound(tl)); + ERRCHK(tl); + return; + } + if (tl->t->tok != ID || !vcc_IdIs(tl->t, "if")) { + VSB_printf(tl->sb, + "'else' must be followed by 'if' or '{'\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + Fb(tl, 1, "else if "); + vcc_NextToken(tl); + vcc_Conditional(tl); + ERRCHK(tl); + L(tl, vcc_Compound(tl)); + ERRCHK(tl); + } else if (vcc_IdIs(tl->t, "elseif") || + vcc_IdIs(tl->t, "elsif") || + vcc_IdIs(tl->t, "elif")) { + Fb(tl, 1, "else if "); + vcc_NextToken(tl); + vcc_Conditional(tl); + ERRCHK(tl); + L(tl, vcc_Compound(tl)); + ERRCHK(tl); + } else { + break; + } + } + C(tl, ";"); +} + +/*-------------------------------------------------------------------- + * SYNTAX: + * Compound: + * '{' Stmt* '}' + * + * Stmt: + * Compound + * IfStmt + * CSRC + * Id(Action) (XXX) + */ + +static void +vcc_Compound(struct vcc *tl) +{ + int i; + + SkipToken(tl, '{'); + Fb(tl, 1, "{\n"); + tl->indent += INDENT; + C(tl, ";"); + while (1) { + ERRCHK(tl); + switch (tl->t->tok) { + case '{': + vcc_Compound(tl); + break; + case '}': + vcc_NextToken(tl); + tl->indent -= INDENT; + Fb(tl, 1, "}\n"); + return; + case CSRC: + if (tl->allow_inline_c) { + Fb(tl, 1, "%.*s\n", + (int) (tl->t->e - (tl->t->b + 2)), + tl->t->b + 1); + vcc_NextToken(tl); + } else { + VSB_printf(tl->sb, + "Inline-C not allowed\n"); + vcc_ErrWhere(tl, tl->t); + } + break; + case EOI: + VSB_printf(tl->sb, + "End of input while in compound statement\n"); + tl->err = 1; + return; + case ID: + if (vcc_IdIs(tl->t, "if")) { + vcc_IfStmt(tl); + break; + } else { + i = vcc_ParseAction(tl); + ERRCHK(tl); + if (i) { + SkipToken(tl, ';'); + break; + } + } + /* FALLTHROUGH */ + default: + /* We deliberately do not mention inline C */ + VSB_printf(tl->sb, + "Expected an action, 'if', '{' or '}'\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + } +} + +/*-------------------------------------------------------------------- + * SYNTAX: + * Function: + * 'sub' ID(name) Compound + */ + +static void +vcc_Function(struct vcc *tl) +{ + int m, i; + + vcc_NextToken(tl); + ExpectErr(tl, ID); + if (!vcc_isCid(tl->t)) { + VSB_printf(tl->sb, + "Names of VCL sub's cannot contain '-'\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + + m = IsMethod(tl->t); + if (m == -2) { + VSB_printf(tl->sb, + "VCL sub's named 'vcl*' are reserved names.\n"); + vcc_ErrWhere(tl, tl->t); + VSB_printf(tl->sb, "Valid vcl_* methods are:\n"); + for (i = 0; method_tab[i].name != NULL; i++) + VSB_printf(tl->sb, "\t%s\n", method_tab[i].name); + return; + } else if (m != -1) { + assert(m < VCL_MET_MAX); + tl->fb = tl->fm[m]; + if (tl->mprocs[m] == NULL) { + (void)vcc_AddDef(tl, tl->t, SYM_SUB); + vcc_AddRef(tl, tl->t, SYM_SUB); + tl->mprocs[m] = vcc_AddProc(tl, tl->t); + } + tl->curproc = tl->mprocs[m]; + Fb(tl, 1, " /* ... from "); + vcc_Coord(tl, tl->fb, NULL); + Fb(tl, 0, " */\n"); + } else { + tl->fb = tl->fc; + i = vcc_AddDef(tl, tl->t, SYM_SUB); + if (i > 1) { + VSB_printf(tl->sb, + "Function %.*s redefined\n", PF(tl->t)); + vcc_ErrWhere(tl, tl->t); + return; + } + tl->curproc = vcc_AddProc(tl, tl->t); + Fh(tl, 0, "static int VGC_function_%.*s " + "(struct vrt_ctx *ctx);\n", PF(tl->t)); + Fc(tl, 1, "\nstatic int __match_proto__(vcl_func_t)\n"); + Fc(tl, 1, "VGC_function_%.*s(struct vrt_ctx *ctx)\n", + PF(tl->t)); + } + vcc_NextToken(tl); + tl->indent += INDENT; + Fb(tl, 1, "{\n"); + L(tl, vcc_Compound(tl)); + if (m == -1) { + /* + * non-method subroutines must have an explicit non-action + * return in case they just fall through the bottom. + */ + Fb(tl, 1, " return(0);\n"); + } + Fb(tl, 1, "}\n"); + tl->indent -= INDENT; + tl->fb = NULL; + tl->curproc = NULL; +} + +/*-------------------------------------------------------------------- + */ + +static void +vcc_Director(struct vcc *tl) +{ + VSB_printf(tl->sb, "\ndirectors are now in directors VMOD.\n"); + vcc_ErrWhere(tl, tl->t); +} + +/*-------------------------------------------------------------------- + * Top level of parser, recognize: + * Inline C-code + * ACL definitions + * Function definitions + * Backend & Director definitions + * End of input + */ + +typedef void parse_f(struct vcc *tl); + +static struct toplev { + const char *name; + parse_f *func; +} toplev[] = { + { "acl", vcc_Acl }, + { "sub", vcc_Function }, + { "backend", vcc_ParseBackend }, + { "director", vcc_Director }, + { "probe", vcc_ParseProbe }, + { "import", vcc_ParseImport }, + { NULL, NULL } +}; + +void +vcc_Parse(struct vcc *tl) +{ + struct toplev *tp; + + while (tl->t->tok != EOI) { + ERRCHK(tl); + switch (tl->t->tok) { + case CSRC: + if (tl->allow_inline_c) { + Fc(tl, 0, "%.*s\n", + (int) (tl->t->e - (tl->t->b + 4)), + tl->t->b + 2); + vcc_NextToken(tl); + } else { + VSB_printf(tl->sb, + "Inline-C not allowed\n"); + vcc_ErrWhere(tl, tl->t); + } + break; + case EOI: + break; + case ID: + for (tp = toplev; tp->name != NULL; tp++) { + if (!vcc_IdIs(tl->t, tp->name)) + continue; + tp->func(tl); + break; + } + if (tp->name != NULL) + break; + /* FALLTHROUGH */ + default: + /* We deliberately do not mention inline-C */ + VSB_printf(tl->sb, "Expected one of\n\t"); + for (tp = toplev; tp->name != NULL; tp++) { + if (tp[1].name == NULL) + VSB_printf(tl->sb, " or "); + VSB_printf(tl->sb, "'%s'", tp->name); + if (tp[1].name != NULL) + VSB_printf(tl->sb, ", "); + } + VSB_printf(tl->sb, "\nFound: "); + vcc_ErrToken(tl, tl->t); + VSB_printf(tl->sb, " at\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + } +} diff --git a/lib/libvcc/vcc_storage.c b/lib/libvcc/vcc_storage.c new file mode 100644 index 0000000..5f9712a --- /dev/null +++ b/lib/libvcc/vcc_storage.c @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 2010 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * All stuff related to the storage.* part of the namespace. + * + * "All" is actually only a wildcard function, which instantiates variables + * on demand under the storage.* tree of the namespace. + * + * About the syntax: + * ----------------- + * + * One of our long term goals is to have dynamic storage configuration, such + * as the ability to add or remove a stevedore on the fly, without restarting + * the worker process. + * + * Even though this goal is far out in the future, it influences the syntax + * design of storage selection from VCL. + * + * In difference from backends, where we know the possible set of backends at + * compile time, we will not in the future know the identity of the stevedores + * available at compile time, so we have to rely on VRT name resolution. + * + * This indicates a namespace on the form storage.. + * + * For each property, we must define a default value if the named stevedore + * does not exists, such that for instance stevedore.forgetit.freespace + * returns zero etc. + * + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "vcc_compile.h" + +#define PFX "storage." + +/*-------------------------------------------------------------------- + * + */ + +static struct var * +vcc_Stv_mkvar(struct vcc *tl, const struct token *t, enum var_type fmt) +{ + struct var *v; + + v = TlAlloc(tl, sizeof *v); + AN(v); + + v->name = TlDupTok(tl, t); + v->r_methods = 0 +#define VCL_MET_MAC(l,u,b) | VCL_MET_##u +#include "tbl/vcl_returns.h" +#undef VCL_MET_MAC + ; + v->fmt = fmt; + + return (v); +} + +static struct stvars { + const char *name; + enum var_type fmt; +} stvars[] = { +#define VRTSTVVAR(nm, vtype, ctype, dval) { #nm, vtype }, +#include "tbl/vrt_stv_var.h" +#undef VRTSTVVAR + { NULL, BOOL } +}; + +struct symbol * +vcc_Stv_Wildcard(struct vcc *tl, const struct token *t, + const struct symbol *wcsym) +{ + const char *p, *q; + struct var *v = NULL; + struct symbol *sym; + struct stvars *sv; + char stv[1024]; + char buf[1024]; + + (void)wcsym; + assert((t->e - t->b) > strlen(PFX)); + assert(!memcmp(t->b, PFX, strlen(PFX))); + + p = t->b + strlen(PFX); + for (q = p; q < t->e && *q != '.'; q++) + continue; + bprintf(stv, "%.*s", (int)(q - p), p); + + if (q == t->e) { + v = vcc_Stv_mkvar(tl, t, BOOL); + bprintf(buf, "VRT_Stv(\"%s\")", stv); + v->rname = TlDup(tl, buf); + } else { + assert(*q == '.'); + q++; + for(sv = stvars; sv->name != NULL; sv++) { + if (strncmp(q, sv->name, t->e - q)) + continue; + if (sv->name[t->e - q] != '\0') + continue; + v = vcc_Stv_mkvar(tl, t, sv->fmt); + bprintf(buf, "VRT_Stv_%s(\"%s\")", sv->name, stv); + v->rname = TlDup(tl, buf); + break; + } + } + + if (v == NULL) + return (NULL); + + sym = VCC_AddSymbolTok(tl, t, SYM_VAR); + AN(sym); + sym->var = v; + sym->fmt = v->fmt; + sym->eval = vcc_Eval_Var; + sym->r_methods = v->r_methods; + + return (sym); +} diff --git a/lib/libvcc/vcc_symb.c b/lib/libvcc/vcc_symb.c new file mode 100644 index 0000000..c3d8a13 --- /dev/null +++ b/lib/libvcc/vcc_symb.c @@ -0,0 +1,142 @@ +/*- + * Copyright (c) 2010 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include + +#include "vcc_compile.h" + +/*--------------------------------------------------------------------*/ + +const char * +VCC_SymKind(struct vcc *tl, const struct symbol *s) +{ + switch(s->kind) { +#define VCC_SYMB(uu, ll) case SYM_##uu: return(#ll); +#include "tbl/symbol_kind.h" +#undef VCC_SYMB + default: + ErrInternal(tl); + VSB_printf(tl->sb, "Symbol Kind 0x%x\n", s->kind); + return("INTERNALERROR"); + } +} + + +static struct symbol * +vcc_AddSymbol(struct vcc *tl, const char *nb, int l, enum symkind kind) +{ + struct symbol *sym; + + VTAILQ_FOREACH(sym, &tl->symbols, list) { + if (sym->nlen != l) + continue; + if (memcmp(nb, sym->name, l)) + continue; + if (kind != sym->kind) + continue; + VSB_printf(tl->sb, "Name Collision: <%.*s> <%s>\n", + l, nb, VCC_SymKind(tl, sym)); + ErrInternal(tl); + return (NULL); + } + ALLOC_OBJ(sym, SYMBOL_MAGIC); + AN(sym); + sym->name = malloc(l + 1L); + AN(sym->name); + memcpy(sym->name, nb, l); + sym->name[l] = '\0'; + sym->nlen = l; + VTAILQ_INSERT_HEAD(&tl->symbols, sym, list); + sym->kind = kind; + return (sym); +} + +struct symbol * +VCC_AddSymbolStr(struct vcc *tl, const char *name, enum symkind kind) +{ + + return (vcc_AddSymbol(tl, name, strlen(name), kind)); +} + +struct symbol * +VCC_AddSymbolTok(struct vcc *tl, const struct token *t, enum symkind kind) +{ + + return (vcc_AddSymbol(tl, t->b, t->e - t->b, kind)); +} + +struct symbol * +VCC_GetSymbolTok(struct vcc *tl, const struct token *tok, enum symkind kind) +{ + struct symbol *sym; + + sym = VCC_FindSymbol(tl, tok, kind); + if (sym == NULL) { + sym = vcc_AddSymbol(tl, tok->b, tok->e - tok->b, kind); + AN(sym); + sym->def_b = tok; + } + return (sym); +} + +struct symbol * +VCC_FindSymbol(struct vcc *tl, const struct token *t, enum symkind kind) +{ + struct symbol *sym; + + assert(t->tok == ID); + VTAILQ_FOREACH(sym, &tl->symbols, list) { + if (sym->kind == SYM_WILDCARD && + (t->e - t->b > sym->nlen) && + !memcmp(sym->name, t->b, sym->nlen)) { + AN(sym->wildcard); + return (sym->wildcard(tl, t, sym)); + } + if (kind != SYM_NONE && kind != sym->kind) + continue; + if (vcc_IdIs(t, sym->name)) + return (sym); + } + return (NULL); +} + +void +VCC_WalkSymbols(struct vcc *tl, symwalk_f *func, enum symkind kind) +{ + struct symbol *sym; + + VTAILQ_FOREACH(sym, &tl->symbols, list) { + if (kind == SYM_NONE || kind == sym->kind) + func(tl, sym); + ERRCHK(tl); + } +} diff --git a/lib/libvcc/vcc_token.c b/lib/libvcc/vcc_token.c new file mode 100644 index 0000000..6201fea --- /dev/null +++ b/lib/libvcc/vcc_token.c @@ -0,0 +1,523 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2011 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "vcc_compile.h" + +/*--------------------------------------------------------------------*/ + +void +vcc_ErrToken(const struct vcc *tl, const struct token *t) +{ + + if (t->tok == EOI) + VSB_printf(tl->sb, "end of input"); + else if (t->tok == CSRC) + VSB_printf(tl->sb, "C{ ... }C"); + else + VSB_printf(tl->sb, "'%.*s'", PF(t)); +} + +void +vcc__ErrInternal(struct vcc *tl, const char *func, unsigned line) +{ + + VSB_printf(tl->sb, "VCL compiler internal error at %s():%u\n", + func, line); + tl->err = 1; +} + +/*-------------------------------------------------------------------- + * Find start of source-line of token + */ + +static void +vcc_iline(const struct token *t, const char **ll, int tail) +{ + const char *p, *b, *x; + + b = t->src->b; + if (ll != NULL) + *ll = b; + x = tail ? t->e - 1 : t->b; + for (p = b; p < x; p++) { + if (*p == '\n') { + if (ll != NULL) + *ll = p + 1; + } + } +} + +/*-------------------------------------------------------------------- + * Find and print src+line+pos of this token + */ + +static void +vcc_icoord(struct vsb *vsb, const struct token *t, int tail) +{ + unsigned lin, pos; + const char *p, *b, *x; + + lin = 1; + pos = 0; + b = t->src->b; + x = tail ? t->e - 1 : t->b; + for (p = b; p < x; p++) { + if (*p == '\n') { + lin++; + pos = 0; + } else if (*p == '\t') { + pos &= ~7; + pos += 8; + } else + pos++; + } + VSB_printf(vsb, "('%s' Line %u Pos %u)", t->src->name, lin, pos + 1); +} + +/*--------------------------------------------------------------------*/ + +void +vcc_Coord(const struct vcc *tl, struct vsb *vsb, const struct token *t) +{ + + if (t == NULL) + t = tl->t; + vcc_icoord(vsb, t, 0); +} + +/*-------------------------------------------------------------------- + * Output one line of source code, starting at 'l' and ending at the + * first NL or 'le'. + */ + +static void +vcc_quoteline(const struct vcc *tl, const char *l, const char *le) +{ + const char *p; + unsigned x, y; + + x = y = 0; + for (p = l; p < le && *p != '\n'; p++) { + if (*p == '\t') { + y &= ~7; + y += 8; + while (x < y) { + VSB_bcat(tl->sb, " ", 1); + x++; + } + } else { + x++; + y++; + VSB_bcat(tl->sb, p, 1); + } + } + VSB_putc(tl->sb, '\n'); +} + +/*-------------------------------------------------------------------- + * Output a marker line for a sourceline starting at 'l' and ending at + * the first NL or 'le'. Characters between 'b' and 'e' are marked. + */ + +static void +vcc_markline(const struct vcc *tl, const char *l, const char *le, + const char *b, const char *e) +{ + const char *p; + unsigned x, y; + char c; + + x = y = 0; + for (p = l; p < le && *p != '\n'; p++) { + if (p >= b && p < e) + c = '#'; + else + c = '-'; + + if (*p == '\t') { + y &= ~7; + y += 8; + } else + y++; + while (x < y) { + VSB_putc(tl->sb, c); + x++; + } + } + VSB_putc(tl->sb, '\n'); +} + +/*--------------------------------------------------------------------*/ +/* XXX: should take first+last token */ + +void +vcc_ErrWhere2(struct vcc *tl, const struct token *t, const struct token *t2) +{ + const char *l1, *l2, *l3; + + if (t == NULL) { + vcc_ErrWhere(tl, t2); + return; + } + vcc_iline(t, &l1, 0); + t2 = VTAILQ_PREV(t2, tokenhead, list); + vcc_iline(t2, &l2, 1); + + + if (l1 == l2) { + vcc_icoord(tl->sb, t, 0); + VSB_cat(tl->sb, " -- "); + vcc_icoord(tl->sb, t2, 1); + VSB_putc(tl->sb, '\n'); + /* Two tokens on same line */ + vcc_quoteline(tl, l1, t->src->e); + vcc_markline(tl, l1, t->src->e, t->b, t2->e); + } else { + /* Two tokens different lines */ + l3 = strchr(l1, '\n'); + AN(l3); + /* XXX: t had better be before t2 */ + vcc_icoord(tl->sb, t, 0); + if (l3 + 1 == l2) { + VSB_cat(tl->sb, " -- "); + vcc_icoord(tl->sb, t2, 1); + } + VSB_putc(tl->sb, '\n'); + vcc_quoteline(tl, l1, t->src->e); + vcc_markline(tl, l1, t->src->e, t->b, t2->e); + if (l3 + 1 != l2) { + VSB_cat(tl->sb, "[...]\n"); + vcc_icoord(tl->sb, t2, 1); + VSB_putc(tl->sb, '\n'); + } + vcc_quoteline(tl, l2, t->src->e); + vcc_markline(tl, l2, t->src->e, t->b, t2->e); + } + VSB_putc(tl->sb, '\n'); + tl->err = 1; +} + +void +vcc_ErrWhere(struct vcc *tl, const struct token *t) +{ + const char *l1; + + vcc_iline(t, &l1, 0); + vcc_icoord(tl->sb, t, 0); + VSB_putc(tl->sb, '\n'); + vcc_quoteline(tl, l1, t->src->e); + vcc_markline(tl, l1, t->src->e, t->b, t->e); + VSB_putc(tl->sb, '\n'); + tl->err = 1; +} + +/*--------------------------------------------------------------------*/ + +void +vcc_NextToken(struct vcc *tl) +{ + + tl->t = VTAILQ_NEXT(tl->t, list); + if (tl->t == NULL) { + VSB_printf(tl->sb, + "Ran out of input, something is missing or" + " maybe unbalanced (...) or {...}\n"); + tl->err = 1; + return; + } +} + +void +vcc__Expect(struct vcc *tl, unsigned tok, unsigned line) +{ + if (tl->t->tok == tok) + return; + VSB_printf(tl->sb, "Expected %s got ", vcl_tnames[tok]); + vcc_ErrToken(tl, tl->t); + VSB_printf(tl->sb, "\n(program line %u), at\n", line); + vcc_ErrWhere(tl, tl->t); +} + +/*-------------------------------------------------------------------- + * Compare ID token to string, return true of match + */ + +int +vcc_IdIs(const struct token *t, const char *p) +{ + const char *q; + + assert(t->tok == ID); + for (q = t->b; q < t->e && *p != '\0'; p++, q++) + if (*q != *p) + return (0); + if (q != t->e || *p != '\0') + return (0); + return (1); +} + +/*-------------------------------------------------------------------- + * Check that we have a C-identifier + */ + +int +vcc_isCid(const struct token *t) +{ + const char *q; + + assert(t->tok == ID); + for (q = t->b; q < t->e; q++) { + if (!isalnum(*q) && *q != '_') + return (0); + } + return (1); +} + +void +vcc_ExpectCid(struct vcc *tl) +{ + + ExpectErr(tl, ID); + ERRCHK(tl); + if (vcc_isCid(tl->t)) + return; + VSB_printf(tl->sb, "Identifier "); + vcc_ErrToken(tl, tl->t); + VSB_printf(tl->sb, + " contains illegal characters, use [0-9a-zA-Z_] only.\n"); + vcc_ErrWhere(tl, tl->t); +} + +/*-------------------------------------------------------------------- + * Decode a string + */ + +static int +vcc_decstr(struct vcc *tl) +{ + char *q; + unsigned int l; + + assert(tl->t->tok == CSTR); + l = (tl->t->e - tl->t->b) - 2; + tl->t->dec = TlAlloc(tl, l + 1); + assert(tl->t->dec != NULL); + q = tl->t->dec; + memcpy(q, tl->t->b + 1, l); + q[l] = '\0'; + return (0); +} + +/*-------------------------------------------------------------------- + * Add a token to the token list. + */ + +void +vcc_AddToken(struct vcc *tl, unsigned tok, const char *b, const char *e) +{ + struct token *t; + + t = TlAlloc(tl, sizeof *t); + assert(t != NULL); + t->tok = tok; + t->b = b; + t->e = e; + t->src = tl->src; + if (tl->t != NULL) + VTAILQ_INSERT_AFTER(&tl->tokens, tl->t, t, list); + else + VTAILQ_INSERT_TAIL(&tl->tokens, t, list); + tl->t = t; +} + +/*-------------------------------------------------------------------- + * Lexical analysis and token generation + */ + +void +vcc_Lexer(struct vcc *tl, struct source *sp) +{ + const char *p, *q; + unsigned u; + + tl->src = sp; + for (p = sp->b; p < sp->e; ) { + + /* Skip any whitespace */ + if (isspace(*p)) { + p++; + continue; + } + + /* Skip '#.*\n' comments */ + if (*p == '#') { + while (p < sp->e && *p != '\n') + p++; + continue; + } + + /* Skip C-style comments */ + if (*p == '/' && p[1] == '*') { + for (q = p + 2; q < sp->e; q++) { + if (*q == '/' && q[1] == '*') { + VSB_printf(tl->sb, + "/* ... */ comment contains /*\n"); + vcc_AddToken(tl, EOI, p, p + 2); + vcc_ErrWhere(tl, tl->t); + vcc_AddToken(tl, EOI, q, q + 2); + vcc_ErrWhere(tl, tl->t); + return; + } + if (*q == '*' && q[1] == '/') { + p = q + 2; + break; + } + } + if (q < sp->e) + continue; + vcc_AddToken(tl, EOI, p, p + 2); + VSB_printf(tl->sb, + "Unterminated /* ... */ comment, starting at\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + + /* Skip C++-style comments */ + if (*p == '/' && p[1] == '/') { + while (p < sp->e && *p != '\n') + p++; + continue; + } + + /* Recognize inline C-code */ + if (*p == 'C' && p[1] == '{') { + for (q = p + 2; q < sp->e; q++) { + if (*q == '}' && q[1] == 'C') { + vcc_AddToken(tl, CSRC, p, q + 2); + break; + } + } + if (q < sp->e) { + p = q + 2; + continue; + } + vcc_AddToken(tl, EOI, p, p + 2); + VSB_printf(tl->sb, + "Unterminated inline C source, starting at\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + + /* Recognize long-strings */ + if (*p == '{' && p[1] == '"') { + for (q = p + 2; q < sp->e; q++) { + if (*q == '"' && q[1] == '}') { + vcc_AddToken(tl, CSTR, p, q + 2); + break; + } + } + if (q < sp->e) { + p = q + 2; + u = tl->t->e - tl->t->b; + u -= 4; /* {" ... "} */ + tl->t->dec = TlAlloc(tl, u + 1 ); + AN(tl->t->dec); + memcpy(tl->t->dec, tl->t->b + 2, u); + tl->t->dec[u] = '\0'; + continue; + } + vcc_AddToken(tl, EOI, p, p + 2); + VSB_printf(tl->sb, + "Unterminated long-string, starting at\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + + /* Match for the fixed tokens (see token.tcl) */ + u = vcl_fixed_token(p, &q); + if (u != 0) { + vcc_AddToken(tl, u, p, q); + p = q; + continue; + } + + /* Match strings */ + if (*p == '"') { + for (q = p + 1; q < sp->e; q++) { + if (*q == '"') { + q++; + break; + } + if (*q == '\r' || *q == '\n') { + vcc_AddToken(tl, EOI, p, q); + VSB_printf(tl->sb, + "Unterminated string at\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + } + vcc_AddToken(tl, CSTR, p, q); + if (vcc_decstr(tl)) + return; + p = q; + continue; + } + + /* Match Identifiers */ + if (isident1(*p)) { + for (q = p; q < sp->e; q++) + if (!isvar(*q)) + break; + vcc_AddToken(tl, ID, p, q); + p = q; + continue; + } + + /* Match numbers { [0-9]+ } */ + if (isdigit(*p)) { + for (q = p; q < sp->e; q++) + if (!isdigit(*q)) + break; + vcc_AddToken(tl, CNUM, p, q); + p = q; + continue; + } + vcc_AddToken(tl, EOI, p, p + 1); + VSB_printf(tl->sb, "Syntax error at\n"); + vcc_ErrWhere(tl, tl->t); + return; + } +} diff --git a/lib/libvcc/vcc_utils.c b/lib/libvcc/vcc_utils.c new file mode 100644 index 0000000..5870af5 --- /dev/null +++ b/lib/libvcc/vcc_utils.c @@ -0,0 +1,255 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "vcc_compile.h" + +#include "vre.h" +#include "vrt.h" +#include "vsa.h" + +/*--------------------------------------------------------------------*/ + +const char * +vcc_regexp(struct vcc *tl) +{ + char buf[BUFSIZ], *p; + vre_t *t; + const char *error; + int erroroffset; + + Expect(tl, CSTR); + if (tl->err) + return (NULL); + memset(&t, 0, sizeof t); + t = VRE_compile(tl->t->dec, 0, &error, &erroroffset); + if (t == NULL) { + VSB_printf(tl->sb, + "Regexp compilation error:\n\n%s\n\n", error); + vcc_ErrWhere(tl, tl->t); + return (NULL); + } + VRE_free(&t); + sprintf(buf, "VGC_re_%u", tl->unique++); + p = TlAlloc(tl, strlen(buf) + 1); + strcpy(p, buf); + + Fh(tl, 0, "static void *%s;\n", buf); + Fi(tl, 0, "\tVRT_re_init(&%s, ",buf); + EncToken(tl->fi, tl->t); + Fi(tl, 0, ");\n"); + Ff(tl, 0, "\tVRT_re_fini(%s);\n", buf); + return (p); +} + +/* + * The IPv6 crew royally screwed up the entire idea behind + * struct sockaddr, and combined with various other incomptency + * in the OS business, that means that there is no sane or even + * remotely portable way to initialize a sockaddr at compile time. + * + * In our case it is slightly more tricky than that, because we don't + * even want to #include the struct sockaddr* definitions. + * + * Instead we make sure the sockaddr is sane (for our values of sane) + * and dump it in binary, using a 64 bit integertype, hoping that this + * will ensure good enough alignment. + */ + +static const char * +vcc_sockaddr(struct vcc *tl, const void *sa, unsigned sal) +{ + unsigned n = (sal + 7) / 8, len; + uint64_t b[n]; + char *p; + + assert(VSA_Sane(sa)); + AN(sa); + AN(sal); + assert(sal < sizeof(struct sockaddr_storage)); + assert(sizeof(unsigned long long) == 8); + + p = TlAlloc(tl, 20); + sprintf(p, "sockaddr_%u", tl->unique++); + + Fh(tl, 0, "static const unsigned long long"); + Fh(tl, 0, " %s[%d] = {\n", p, n); + memcpy(b, sa, sal); + for (len = 0; len sb, + "%s '%.*s' could not be resolved to an IP address:\n", + errid, PF(t_err)); + VSB_printf(tl->sb, + "\t%s\n" + "(Sorry if that error message is gibberish.)\n", + gai_strerror(error)); + vcc_ErrWhere(tl, t_err); + return; + } + + for (res = res0; res; res = res->ai_next) { + for (pp = protos; pp->name != NULL; pp++) + if (res->ai_family == pp->family) + break; + if (pp->name == NULL) { + /* Unknown proto, ignore */ + continue; + } + if (pp->l == res->ai_addrlen && + !memcmp(&pp->sa, res->ai_addr, pp->l)) { + /* + * Same address we already emitted. + * This can happen using /etc/hosts + */ + continue; + } + + if (pp->l != 0 || retval == maxips) { + VSB_printf(tl->sb, + "%s %.*s: resolves to too many addresses.\n" + "Only one IPv4 %s IPv6 are allowed.\n" + "Please specify which exact address " + "you want to use, we found all of these:\n", + errid, PF(t_err), + maxips > 1 ? "and one" : "or"); + for (res1 = res0; res1 != NULL; res1 = res1->ai_next) { + error = getnameinfo(res1->ai_addr, + res1->ai_addrlen, hbuf, sizeof hbuf, + NULL, 0, NI_NUMERICHOST); + AZ(error); + VSB_printf(tl->sb, "\t%s\n", hbuf); + } + freeaddrinfo(res0); + vcc_ErrWhere(tl, t_err); + return; + } + + pp->l = res->ai_addrlen; + assert(pp->l < sizeof(struct sockaddr_storage)); + memcpy(&pp->sa, res->ai_addr, pp->l); + + error = getnameinfo(res->ai_addr, res->ai_addrlen, + hbuf, sizeof hbuf, NULL, 0, NI_NUMERICHOST); + AZ(error); + + Fh(tl, 0, "\n/* \"%s\" -> %s */\n", host, hbuf); + *(pp->dst) = vcc_sockaddr(tl, &pp->sa, pp->l); + if (pp->dst_ascii != NULL) { + *pp->dst_ascii = TlDup(tl, hbuf); + } + retval++; + } + if (p_ascii != NULL) { + error = getnameinfo(res0->ai_addr, + res0->ai_addrlen, NULL, 0, hbuf, sizeof hbuf, + NI_NUMERICSERV); + AZ(error); + *p_ascii = TlDup(tl, hbuf); + } + if (retval == 0) { + VSB_printf(tl->sb, + "%s '%.*s': resolves to " + "neither IPv4 nor IPv6 addresses.\n", + errid, PF(t_err) ); + vcc_ErrWhere(tl, t_err); + } +} diff --git a/lib/libvcc/vcc_var.c b/lib/libvcc/vcc_var.c new file mode 100644 index 0000000..74713b8 --- /dev/null +++ b/lib/libvcc/vcc_var.c @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2011 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include + +#include "vcc_compile.h" +#include "vct.h" + +/*--------------------------------------------------------------------*/ + +struct symbol * +vcc_Var_Wildcard(struct vcc *tl, const struct token *t, const struct symbol *wc) +{ + struct symbol *sym; + struct var *v; + const struct var *vh; + int l, i; + char c; + char buf[258]; + char cnam[256]; + + vh = wc->var; + + v = TlAlloc(tl, sizeof *v); + AN(v); + + assert(vh->fmt == HEADER); + v->name = TlDupTok(tl, t); + v->r_methods = vh->r_methods; + v->w_methods = vh->w_methods; + v->fmt = vh->fmt; + + /* Create a C-name version of the header name */ + l = strlen(v->name + vh->len) + 1; + for (i = 0; i < l - 1; i++) { + c = *(v->name + vh->len + i); + if (vct_isalpha(c) || vct_isdigit(c)) + cnam[i] = c; + else + cnam[i] = '_'; + } + cnam[i] = '\0'; + + /* Create the static identifier */ + Fh(tl, 0, "static const struct gethdr_s VGC_%s_%s =\n", + vh->rname, cnam); + Fh(tl, 0, " { %s, \"\\%03o%s:\"};\n", + vh->rname, (unsigned)l, v->name + vh->len); + + bprintf(buf, "&VGC_%s_%s", vh->rname, cnam); + v->rname = TlDup(tl, buf); + bprintf(buf, "VRT_SetHdr(ctx, %s, ", v->rname); + v->lname = TlDup(tl, buf); + + sym = VCC_AddSymbolTok(tl, t, SYM_VAR); + AN(sym); + sym->var = v; + sym->fmt = v->fmt; + sym->eval = vcc_Eval_Var; + sym->r_methods = v->r_methods; + return (sym); +} + +/*--------------------------------------------------------------------*/ + +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); + } + return (v); + } + VSB_printf(tl->sb, "Unknown variable "); + vcc_ErrToken(tl, t); + VSB_cat(tl->sb, "\nAt: "); + vcc_ErrWhere(tl, t); + return (NULL); +} diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c new file mode 100644 index 0000000..7eb9d32c --- /dev/null +++ b/lib/libvcc/vcc_vmod.c @@ -0,0 +1,204 @@ +/*- + * Copyright (c) 2010-2013 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include + +#include "vcc_compile.h" + +#include "vmod_abi.h" + +void +vcc_ParseImport(struct vcc *tl) +{ + void *hdl; + char fn[1024]; + char buf[256]; + struct token *mod, *t1; + const char *modname; + const char *proto; + const char *abi; + const char **spec; + struct symbol *sym; + const struct symbol *osym; + const char *p; + // int *modlen; + + t1 = tl->t; + SkipToken(tl, ID); /* "import" */ + + ExpectErr(tl, ID); + mod = tl->t; + vcc_NextToken(tl); + + osym = VCC_FindSymbol(tl, mod, SYM_NONE); + if (osym != NULL && osym->kind != SYM_VMOD) { + VSB_printf(tl->sb, "Module %.*s conflics with other symbol.\n", + PF(mod)); + vcc_ErrWhere2(tl, t1, tl->t); + return; + } + if (osym != NULL) { + VSB_printf(tl->sb, "Module %.*s already imported.\n", + PF(mod)); + vcc_ErrWhere2(tl, t1, tl->t); + VSB_printf(tl->sb, "Previous import was here:\n"); + vcc_ErrWhere2(tl, osym->def_b, osym->def_e); + return; + } + + bprintf(fn, "%.*s", PF(mod)); + sym = VCC_AddSymbolStr(tl, fn, SYM_VMOD); + ERRCHK(tl); + AN(sym); + sym->def_b = t1; + sym->def_e = tl->t; + + if (tl->t->tok == ID) { + if (!tl->unsafe_path) { + VSB_printf(tl->sb, + "'import ... from path...'" + " not allowed.\nAt:"); + vcc_ErrToken(tl, tl->t); + vcc_ErrWhere(tl, tl->t); + return; + } + if (!vcc_IdIs(tl->t, "from")) { + VSB_printf(tl->sb, "Expected 'from path...'\n"); + vcc_ErrWhere(tl, tl->t); + return; + } + vcc_NextToken(tl); + ExpectErr(tl, CSTR); + bprintf(fn, "%s", tl->t->dec); + vcc_NextToken(tl); + } else { + bprintf(fn, "%s/libvmod_%.*s.so", tl->vmod_dir, PF(mod)); + } + + Fh(tl, 0, "static void *VGC_vmod_%.*s;\n", PF(mod)); + + Fi(tl, 0, "\tif (VRT_Vmod_Init(&VGC_vmod_%.*s,\n", PF(mod)); + Fi(tl, 0, "\t &Vmod_%.*s_Func,\n", PF(mod)); + Fi(tl, 0, "\t sizeof(Vmod_%.*s_Func),\n", PF(mod)); + Fi(tl, 0, "\t \"%.*s\",\n", PF(mod)); + Fi(tl, 0, "\t "); + EncString(tl->fi, fn, NULL, 0); + Fi(tl, 0, ",\n\t "); + Fi(tl, 0, "cli))\n"); + Fi(tl, 0, "\t\treturn(1);\n"); + + SkipToken(tl, ';'); + + hdl = dlopen(fn, RTLD_NOW | RTLD_LOCAL); + if (hdl == NULL) { + VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", + PF(mod), fn, dlerror()); + vcc_ErrWhere(tl, mod); + return; + } + + bprintf(buf, "Vmod_%.*s_Name", PF(mod)); + modname = dlsym(hdl, buf); + if (modname == NULL) { + VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", + PF(mod), fn, "Symbol Vmod_Name not found"); + vcc_ErrWhere(tl, mod); + return; + } + if (!vcc_IdIs(mod, modname)) { + VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n", + PF(mod), fn); + VSB_printf(tl->sb, "\tModule has wrong name: <%s>\n", modname); + vcc_ErrWhere(tl, mod); + return; + } + + bprintf(buf, "Vmod_%.*s_ABI", PF(mod)); + abi = dlsym(hdl, buf); + if (abi == NULL || strcmp(abi, VMOD_ABI_Version) != 0) { + VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n", + PF(mod), fn); + VSB_printf(tl->sb, "\tABI mismatch, expected <%s>, got <%s>\n", + VMOD_ABI_Version, abi); + vcc_ErrWhere(tl, mod); + return; + } + + bprintf(buf, "Vmod_%.*s_Proto", PF(mod)); + proto = dlsym(hdl, buf); + if (proto == NULL) { + VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", + PF(mod), fn, "Symbol Vmod_Proto not found"); + vcc_ErrWhere(tl, mod); + return; + } + bprintf(buf, "Vmod_%.*s_Spec", PF(mod)); + spec = dlsym(hdl, buf); + if (spec == NULL) { + VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", + PF(mod), fn, "Symbol Vmod_Spec not found"); + vcc_ErrWhere(tl, mod); + return; + } + Fh(tl, 0, "static struct vmod_priv vmod_priv_%.*s;\n", PF(mod)); + for (; *spec != NULL; spec++) { + p = *spec; + if (!strcmp(p, "OBJ")) { + p += strlen(p) + 1; + sym = VCC_AddSymbolStr(tl, p, SYM_OBJECT); + XXXAN(sym); + sym->args = p; + } else if (!strcmp(p, "INIT")) { + p += strlen(p) + 1; + Fi(tl, 0, "\t%s(&vmod_priv_%.*s, &VCL_conf);\n", + p, PF(mod)); + } else { + sym = VCC_AddSymbolStr(tl, p, SYM_FUNC); + ERRCHK(tl); + AN(sym); + sym->eval = vcc_Eval_SymFunc; + p += strlen(p) + 1; + sym->cfunc = p; + p += strlen(p) + 1; + sym->args = p; + + /* Functions which return VOID are procedures */ + if (!memcmp(p, "VOID\0", 5)) + sym->kind = SYM_PROC; + } + } + Fh(tl, 0, "\n%s\n", proto); + + /* XXX: zero the function pointer structure ?*/ + Ff(tl, 0, "\tvmod_priv_fini(&vmod_priv_%.*s);\n", PF(mod)); + Ff(tl, 0, "\tVRT_Vmod_Fini(&VGC_vmod_%.*s);\n", PF(mod)); +} diff --git a/lib/libvcc/vcc_xref.c b/lib/libvcc/vcc_xref.c new file mode 100644 index 0000000..c3ef375 --- /dev/null +++ b/lib/libvcc/vcc_xref.c @@ -0,0 +1,388 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2011 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file contains code for two cross-reference or consistency checks. + * + * The first check is simply that all subroutine, acls and backends are + * both defined and referenced. Complaints about referenced but undefined + * or defined but unreferenced objects will be emitted. + * + * The second check recursively decends through subroutine calls to make + * sure that action actions are correct for the methods through which + * they are called. + */ + +#include "config.h" + +#include + +#include "vcc_compile.h" + +/*--------------------------------------------------------------------*/ + +struct proccall { + VTAILQ_ENTRY(proccall) list; + struct proc *p; + struct token *t; +}; + +struct procuse { + VTAILQ_ENTRY(procuse) list; + const struct token *t; + unsigned mask; + const char *use; +}; + +struct proc { + VTAILQ_HEAD(,proccall) calls; + VTAILQ_HEAD(,procuse) uses; + struct token *name; + unsigned ret_bitmap; + unsigned exists; + unsigned called; + unsigned active; + struct token *return_tok[VCL_RET_MAX]; +}; + +/*-------------------------------------------------------------------- + * Keep track of definitions and references + */ + +void +vcc_AddRef(struct vcc *tl, const struct token *t, enum symkind kind) +{ + struct symbol *sym; + + sym = VCC_GetSymbolTok(tl, t, kind); + AN(sym); + sym->nref++; +} + +int +vcc_AddDef(struct vcc *tl, const struct token *t, enum symkind kind) +{ + struct symbol *sym; + + sym = VCC_GetSymbolTok(tl, t, kind); + AN(sym); + sym->ndef++; + return (sym->ndef); +} + +/*--------------------------------------------------------------------*/ + +static void +vcc_checkref(struct vcc *tl, const struct symbol *sym) +{ + + if (sym->ndef == 0 && sym->nref != 0) { + VSB_printf(tl->sb, "Undefined %s %.*s, first reference:\n", + VCC_SymKind(tl, sym), PF(sym->def_b)); + vcc_ErrWhere(tl, sym->def_b); + } else if (sym->ndef != 0 && sym->nref == 0) { + VSB_printf(tl->sb, "Unused %s %.*s, defined:\n", + VCC_SymKind(tl, sym), PF(sym->def_b)); + vcc_ErrWhere(tl, sym->def_b); + if (!tl->err_unref) { + VSB_printf(tl->sb, "(That was just a warning)\n"); + tl->err = 0; + } + } +} + +int +vcc_CheckReferences(struct vcc *tl) +{ + + VCC_WalkSymbols(tl, vcc_checkref, SYM_NONE); + return (tl->err); +} + +/*-------------------------------------------------------------------- + * Returns checks + */ + +static struct proc * +vcc_findproc(struct vcc *tl, struct token *t) +{ + struct symbol *sym; + struct proc *p; + + + sym = VCC_GetSymbolTok(tl, t, SYM_SUB); + AN(sym); + if (sym->proc != NULL) + return (sym->proc); + + p = TlAlloc(tl, sizeof *p); + assert(p != NULL); + VTAILQ_INIT(&p->calls); + VTAILQ_INIT(&p->uses); + p->name = t; + sym->proc = p; + return (p); +} + +struct proc * +vcc_AddProc(struct vcc *tl, struct token *t) +{ + struct proc *p; + + p = vcc_findproc(tl, t); + p->name = t; /* make sure the name matches the definition */ + p->exists++; + return (p); +} + +void +vcc_AddUses(struct vcc *tl, const struct token *t, unsigned mask, + const char *use) +{ + struct procuse *pu; + + if (tl->curproc == NULL) /* backend */ + return; + pu = TlAlloc(tl, sizeof *pu); + assert(pu != NULL); + pu->t = t; + pu->mask = mask; + pu->use = use; + VTAILQ_INSERT_TAIL(&tl->curproc->uses, pu, list); +} + +void +vcc_AddCall(struct vcc *tl, struct token *t) +{ + struct proccall *pc; + struct proc *p; + + p = vcc_findproc(tl, t); + pc = TlAlloc(tl, sizeof *pc); + assert(pc != NULL); + pc->p = p; + pc->t = t; + VTAILQ_INSERT_TAIL(&tl->curproc->calls, pc, list); +} + +void +vcc_ProcAction(struct proc *p, unsigned returns, struct token *t) +{ + + assert(returns < VCL_RET_MAX); + p->ret_bitmap |= (1U << returns); + /* Record the first instance of this return */ + if (p->return_tok[returns] == NULL) + p->return_tok[returns] = t; +} + +static int +vcc_CheckActionRecurse(struct vcc *tl, struct proc *p, unsigned bitmap) +{ + unsigned u; + struct proccall *pc; + + if (!p->exists) { + VSB_printf(tl->sb, "Function %.*s does not exist\n", + PF(p->name)); + return (1); + } + if (p->active) { + VSB_printf(tl->sb, "Function recurses on\n"); + vcc_ErrWhere(tl, p->name); + return (1); + } + u = p->ret_bitmap & ~bitmap; + if (u) { + +#define VCL_RET_MAC(l, U, B) \ + if (u & (1 << (VCL_RET_##U))) { \ + VSB_printf(tl->sb, "Invalid return \"" #l "\"\n");\ + vcc_ErrWhere(tl, p->return_tok[VCL_RET_##U]); \ + } +#include "tbl/vcl_returns.h" +#undef VCL_RET_MAC + + VSB_printf(tl->sb, "\n...in subroutine \"%.*s\"\n", + PF(p->name)); + vcc_ErrWhere(tl, p->name); + return (1); + } + p->active = 1; + VTAILQ_FOREACH(pc, &p->calls, list) { + if (vcc_CheckActionRecurse(tl, pc->p, bitmap)) { + VSB_printf(tl->sb, "\n...called from \"%.*s\"\n", + PF(p->name)); + vcc_ErrWhere(tl, pc->t); + return (1); + } + } + p->active = 0; + p->called++; + return (0); +} + +/*--------------------------------------------------------------------*/ + +static void +vcc_checkaction1(struct vcc *tl, const struct symbol *sym) +{ + struct proc *p; + struct method *m; + int i; + + p = sym->proc; + AN(p); + i = IsMethod(p->name); + if (i < 0) + return; + m = method_tab + i; + if (vcc_CheckActionRecurse(tl, p, m->ret_bitmap)) { + VSB_printf(tl->sb, + "\n...which is the \"%s\" method\n", m->name); + VSB_printf(tl->sb, "Legal returns are:"); +#define VCL_RET_MAC(l, U, B) \ + if (m->ret_bitmap & ((1 << VCL_RET_##U))) \ + VSB_printf(tl->sb, " \"%s\"", #l); + +#include "tbl/vcl_returns.h" +#undef VCL_RET_MAC + VSB_printf(tl->sb, "\n"); + tl->err = 1; + } + +} + +static void +vcc_checkaction2(struct vcc *tl, const struct symbol *sym) +{ + struct proc *p; + + p = sym->proc; + AN(p); + + if (p->called) + return; + VSB_printf(tl->sb, "Function unused\n"); + vcc_ErrWhere(tl, p->name); + if (!tl->err_unref) { + VSB_printf(tl->sb, "(That was just a warning)\n"); + tl->err = 0; + } +} + +int +vcc_CheckAction(struct vcc *tl) +{ + + VCC_WalkSymbols(tl, vcc_checkaction1, SYM_SUB); + if (tl->err) + return (tl->err); + VCC_WalkSymbols(tl, vcc_checkaction2, SYM_SUB); + return (tl->err); +} + +/*--------------------------------------------------------------------*/ + +static struct procuse * +vcc_FindIllegalUse(const struct proc *p, const struct method *m) +{ + struct procuse *pu; + + VTAILQ_FOREACH(pu, &p->uses, list) + if (!(pu->mask & m->bitval)) + return (pu); + return (NULL); +} + +static int +vcc_CheckUseRecurse(struct vcc *tl, const struct proc *p, + struct method *m) +{ + struct proccall *pc; + struct procuse *pu; + + pu = vcc_FindIllegalUse(p, m); + if (pu != NULL) { + VSB_printf(tl->sb, + "'%.*s': %s from method '%.*s'.\n", + PF(pu->t), pu->use, PF(p->name)); + vcc_ErrWhere(tl, pu->t); + VSB_printf(tl->sb, "\n...in subroutine \"%.*s\"\n", + PF(p->name)); + vcc_ErrWhere(tl, p->name); + return (1); + } + VTAILQ_FOREACH(pc, &p->calls, list) { + if (vcc_CheckUseRecurse(tl, pc->p, m)) { + VSB_printf(tl->sb, "\n...called from \"%.*s\"\n", + PF(p->name)); + vcc_ErrWhere(tl, pc->t); + return (1); + } + } + return (0); +} + +static void +vcc_checkuses(struct vcc *tl, const struct symbol *sym) +{ + struct proc *p; + struct method *m; + struct procuse *pu; + int i; + + p = sym->proc; + AN(p); + + i = IsMethod(p->name); + if (i < 0) + return; + m = method_tab + i; + pu = vcc_FindIllegalUse(p, m); + if (pu != NULL) { + VSB_printf(tl->sb, + "'%.*s': %s in method '%.*s'.", + PF(pu->t), pu->use, PF(p->name)); + VSB_cat(tl->sb, "\nAt: "); + vcc_ErrWhere(tl, pu->t); + return; + } + if (vcc_CheckUseRecurse(tl, p, m)) { + VSB_printf(tl->sb, + "\n...which is the \"%s\" method\n", m->name); + return; + } +} + +int +vcc_CheckUses(struct vcc *tl) +{ + + VCC_WalkSymbols(tl, vcc_checkuses, SYM_SUB); + return (tl->err); +} diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py new file mode 100755 index 0000000..2b6db42 --- /dev/null +++ b/lib/libvcc/vmodtool.py @@ -0,0 +1,553 @@ +#!/usr/bin/env python +#- +# Copyright (c) 2010-2013 Varnish Software AS +# All rights reserved. +# +# Author: Poul-Henning Kamp +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# Read the vmod.spec file and produce the vmod.h and vmod.c files. +# +# vmod.h contains the prototypes for the published functions, the module +# C-code should include this file to ensure type-consistency. +# +# vmod.c contains the symbols which VCC and varnishd will use to access +# the module: A structure of properly typed function pointers, the +# size of this structure in bytes, and the definition of the structure +# as a string, suitable for inclusion in the C-source of the compile VCL +# program. + +import sys +import re + +if len(sys.argv) == 2: + specfile = sys.argv[1] +else: + specfile = "vmod.vcc" + +ctypes = { + 'BACKEND': "VCL_BACKEND", + 'BOOL': "VCL_BOOL", + 'DURATION': "VCL_DURATION", + 'ENUM': "VCL_ENUM", + 'HEADER': "const struct gethdr_s *", + 'INT': "VCL_INT", + 'IP': "VCL_IP", + 'PRIV_CALL': "struct vmod_priv *", + 'PRIV_VCL': "struct vmod_priv *", + 'REAL': "VCL_REAL", + 'STRING': "VCL_STRING", + 'STRING_LIST': "const char *, ...", + 'TIME': "VCL_TIME", + 'VOID': "VCL_VOID", +} + +####################################################################### + +def file_header(fo): + fo.write("""/* + * NB: This file is machine generated, DO NOT EDIT! + * + * Edit vmod.vcc and run vmod.py instead + */ + +""") + +####################################################################### + +def is_c_name(s): + return None != re.match("^[a-z][a-z0-9_]*$", s) + +####################################################################### + +class token(object): + def __init__(self, ln, ch, str): + self.ln = ln + self.ch = ch + self.str = str + + def __repr__(self): + return "<@%d \"%s\">" % (self.ln, self.str) + +####################################################################### + +class vmod(object): + def __init__(self, nam): + if not is_c_name(nam): + raise Exception("Module name '%s' is illegal" % nam) + self.nam = nam + self.init = None + self.funcs = list() + self.objs = list() + + def set_init(self, nam): + if self.init != None: + raise Exception("Module %s already has Init" % self.nam) + if not is_c_name(nam): + raise Exception("Init name '%s' is illegal" % nam) + self.init = nam + + def add_func(self, fn): + self.funcs.append(fn) + + def add_obj(self, obj): + self.objs.append(obj) + obj.set_modnam(self.nam) + + def c_proto(self, fo): + for o in self.objs: + o.c_proto(fo) + fo.write("\n") + for f in self.funcs: + f.c_proto(fo) + if self.init != None: + fo.write("\n") + fo.write("int " + self.init) + fo.write( + "(struct vmod_priv *, const struct VCL_conf *);\n") + #fo.write("\n") + #fo.write("extern const void * const Vmod_" + self.nam + "_Id;\n") + + def c_typedefs_(self): + l = list() + for o in self.objs: + for t in o.c_typedefs(self.nam): + l.append(t) + l.append("") + l.append("/* Functions */") + for f in self.funcs: + l.append(f.c_typedef(self.nam)) + l.append("") + return l + + def c_typedefs(self, fo): + for i in self.c_typedefs_(): + fo.write(i + "\n") + + def c_vmod(self, fo): + fo.write('const char Vmod_' + self.nam + '_Name[] =') + fo.write(' \"' + self.nam + '";\n') + fo.write("\n") + + cs = self.c_struct() + fo.write("const " + cs + ' Vmod_' + self.nam + '_Func = ') + fo.write(self.c_initializer()) + fo.write("\n") + + fo.write("\n") + fo.write("const int Vmod_" + self.nam + '_Len =') + fo.write(" sizeof(Vmod_" + self.nam + "_Func);\n") + fo.write("\n") + + fo.write("const char Vmod_" + self.nam + "_Proto[] =\n") + for t in self.c_typedefs_(): + fo.write('\t"' + t + '\\n"\n') + fo.write('\t"\\n"\n') + for i in (cs + " Vmod_" + self.nam + '_Func;').split("\n"): + fo.write('\n\t"' + i + '\\n"') + fo.write(";\n\n") + + fo.write(self.c_strspec()) + + fo.write("\n") + fo.write('const char Vmod_' + self.nam + '_ABI[] =') + fo.write(' VMOD_ABI_Version;\n') + #fo.write("\n") + #fo.write('const void * const Vmod_' + self.nam + '_Id =') + #fo.write(' &Vmod_' + self.nam + '_Id;\n') + + def c_initializer(self): + s = '{\n' + for o in self.objs: + s += o.c_initializer() + + s += "\n\t/* Functions */\n" + for f in self.funcs: + s += f.c_initializer() + + s += "\n\t/* Init/Fini */\n" + if self.init != None: + s += "\t" + self.init + ",\n" + s += "};" + + return s + + def c_struct(self): + s = 'struct Vmod_' + self.nam + '_Func {\n' + for o in self.objs: + s += o.c_struct(self.nam) + + s += "\n\t/* Functions */\n" + for f in self.funcs: + s += f.c_struct(self.nam) + + s += "\n\t/* Init/Fini */\n" + if self.init != None: + s += "\tvmod_init_f\t*_init;\n" + s += '}' + return s + + def c_strspec(self): + s = "const char * const Vmod_" + self.nam + "_Spec[] = {\n" + + for o in self.objs: + s += o.c_strspec(self.nam) + + s += "\n\t/* Functions */\n" + for f in self.funcs: + s += '\t"' + f.c_strspec(self.nam) + '",\n' + + s += "\n\t/* Init/Fini */\n" + if self.init != None: + s += '\t"INIT\\0Vmod_' + self.nam + '_Func._init",\n' + + s += "\t0\n" + s += "};\n" + return s + +####################################################################### + +class func(object): + def __init__(self, nam, retval, al): + #if not is_c_name(nam): + # raise Exception("Func name '%s' is illegal" % nam) + if retval not in ctypes: + raise Exception( + "Return type '%s' not a valid type" % retval) + self.nam = nam + self.cnam = nam.replace(".", "_") + self.al = al + self.retval = retval + self.pfx = None + + def __repr__(self): + return "" % (self.retval, self.nam) + + def set_pfx(self, s): + self.pfx = s + + def c_proto(self, fo, fini=False): + fo.write(ctypes[self.retval]) + fo.write(" vmod_" + self.cnam + "(") + p = "" + if not fini: + fo.write("const struct vrt_ctx *") + p = ", " + if self.pfx != None: + fo.write(p + self.pfx) + p = ", " + for a in self.al: + fo.write(p + ctypes[a.typ]) + p = ", " + if a.nam != None: + fo.write(" " + a.nam) + fo.write(");\n") + + def c_typedef(self, modname, fini=False): + s = "typedef " + s += ctypes[self.retval] + s += " td_" + modname + "_" + self.cnam + "(" + p = "" + if not fini: + s += "const struct vrt_ctx *" + p = ", " + if self.pfx != None: + s += p + self.pfx + p = ", " + for a in self.al: + s += p + ctypes[a.typ] + p = ", " + s += ");" + return s + + def c_struct(self, modname): + s = '\ttd_' + modname + "_" + self.cnam + while len(s.expandtabs()) < 40: + s += "\t" + s += "*" + self.cnam + ";\n" + return s + + def c_initializer(self): + return "\tvmod_" + self.cnam + ",\n" + + def c_strspec(self, modnam): + s = modnam + "." + self.nam + s += "\\0" + s += "Vmod_" + modnam + "_Func." + self.cnam + "\\0" + s += self.retval + "\\0" + for a in self.al: + s += a.c_strspec() + return s + +####################################################################### + +class obj(object): + def __init__(self, nam): + self.nam = nam + self.init = None + self.fini = None + self.methods = list() + + def set_modnam(self, modnam): + self.st = "struct vmod_" + modnam + "_" + self.nam + self.init.set_pfx(self.st + " **, const char *") + self.fini.set_pfx(self.st + " **") + for m in self.methods: + m.set_pfx(self.st + " *") + + def set_init(self, f): + self.init = f + self.fini = func(f.nam, "VOID", []) + self.init.cnam += "__init" + self.fini.cnam += "__fini" + + def add_method(self, m): + self.methods.append(m) + + def c_typedefs(self, modnam): + l = list() + l.append("/* Object " + self.nam + " */") + l.append(self.st + ";") + l.append(self.init.c_typedef(modnam) + "") + l.append(self.fini.c_typedef(modnam, fini=True) + "") + for m in self.methods: + l.append(m.c_typedef(modnam) + "") + return l + + def c_proto(self, fo): + fo.write(self.st + ";\n") + self.init.c_proto(fo) + self.fini.c_proto(fo, fini = True) + for m in self.methods: + m.c_proto(fo) + + def c_struct(self, modnam): + s = "\t/* Object " + self.nam + " */\n" + s += self.init.c_struct(modnam) + s += self.fini.c_struct(modnam) + for m in self.methods: + s += m.c_struct(modnam) + return s + + def c_initializer(self): + s = "\t/* Object " + self.nam + " */\n" + s += self.init.c_initializer() + s += self.fini.c_initializer() + for m in self.methods: + s += m.c_initializer() + return s + + def c_strspec(self, modnam): + s = "\t/* Object " + self.nam + " */\n" + s += '\t"OBJ\\0"\n' + s += '\t\t"' + self.init.c_strspec(modnam) + '\\0"\n' + s += '\t\t"' + self.st + '\\0"\n' + s += '\t\t"' + self.fini.c_strspec(modnam) + '\\0"\n' + for m in self.methods: + s += '\t\t"' + m.c_strspec(modnam) + '\\0"\n' + s += '\t\t"\\0",\n' + return s + +####################################################################### + +class arg(object): + def __init__(self, typ, nam = None, det = None): + self.nam = nam + self.typ = typ + self.det = det + + def __repr__(self): + return "" % (self.nam, self.typ, str(self.det)) + + def c_strspec(self): + if self.det == None: + return self.typ + "\\0" + else: + return self.det + return "??" + +####################################################################### + +f = open(specfile, "r") +tl = list() +lines = list() +ln = 0 +for l in f: + ln += 1 + lines.append(l) + if l == "": + continue + l = re.sub("[ \t]*#.*$", "", l) + l = re.sub("[ \t]*\n", "", l) + l = re.sub("([(){},])", r' \1 ', l) + if l == "": + continue + for j in l.split(): + tl.append(token(ln, 0, j)) +f.close() + +####################################################################### +# +# +def parse_enum2(tl): + t = tl.pop(0) + if t.str != "{": + raise Exception("expected \"{\"") + s = "ENUM\\0" + while True: + t = tl.pop(0) + if t.str == "}": + break + s += t.str + "\\0" + if tl[0].str == ",": + tl.pop(0) + elif tl[0].str != "}": + raise Exception("Expceted \"}\" or \",\"") + s += "\\0" + return arg("ENUM", det=s) + +####################################################################### +# +# + +def parse_func(tl, rt_type = None, obj=None): + al = list() + if rt_type == None: + t = tl.pop(0) + rt_type = t.str + if rt_type not in ctypes: + raise Exception( + "Return type '%s' not a valid type" % rt_type) + + t = tl.pop(0) + fname = t.str + if obj != None and fname[0] == "." and is_c_name(fname[1:]): + fname = obj + fname + elif not is_c_name(fname): + raise Exception("Function name '%s' is illegal" % fname) + + t = tl.pop(0) + if t.str != "(": + raise Exception("Expected \"(\" got \"%s\"", t.str) + + while True: + t = tl.pop(0) + if t.str == ")": + break + if t.str == "ENUM": + al.append(parse_enum2(tl)) + elif t.str in ctypes: + al.append(arg(t.str)) + else: + raise Exception("ARG? %s" % t.str) + if is_c_name(tl[0].str): + al[-1].nam = tl[0].str + t = tl.pop(0) + if tl[0].str == ",": + tl.pop(0) + elif tl[0].str != ")": + raise Exception("Expceted \")\" or \",\"") + if t.str != ")": + raise Exception("End Of Input looking for ')'") + f = func(fname, rt_type, al) + return f + +####################################################################### +# +# + +def parse_obj(tl): + o = obj(tl[0].str) + f = parse_func(tl, "VOID") + o.set_init(f) + t = tl.pop(0) + assert t.str == "{" + while True: + t = tl.pop(0) + if t.str == "}": + break + assert t.str == "Method" + f = parse_func(tl, obj=o.nam) + o.add_method(f) + return o + +####################################################################### +# The first thing in the file must be the Module declaration +# + +t = tl.pop(0) +if t.str != "Module": + raise Exception("\"Module\" must be first in file") +t = tl.pop(0) +vmod = vmod(t.str) + +####################################################################### +# Parse the rest of the file +# + +while len(tl) > 0: + t = tl.pop(0) + + if t.str == "Init": + t = tl.pop(0) + vmod.set_init(t.str) + elif t.str == "Function": + f = parse_func(tl) + vmod.add_func(f) + elif t.str == "Object": + o = parse_obj(tl) + vmod.add_obj(o) + else: + raise Exception("Expected \"Init\", \"Fini\" or \"Function\"") + +####################################################################### +# Parsing done, now process +# + +fc = open("vcc_if.c", "w") +fh = open("vcc_if.h", "w") + +file_header(fc) +file_header(fh) + +fh.write('struct vrt_ctx;\n') +fh.write('struct VCL_conf;\n') +fh.write('struct vmod_priv;\n') +fh.write("\n"); + +vmod.c_proto(fh) + +fc.write("""#include "config.h" + +#include "vrt.h" +#include "vcc_if.h" +#include "vmod_abi.h" + + +""") + +vmod.c_typedefs(fc) +vmod.c_vmod(fc) + +fc.close() +fh.close() diff --git a/lib/libvcl/Makefile.am b/lib/libvcl/Makefile.am deleted file mode 100644 index 91bc0d3..0000000 --- a/lib/libvcl/Makefile.am +++ /dev/null @@ -1,44 +0,0 @@ -# - -AM_LDFLAGS = $(AM_LT_LDFLAGS) - -AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include - -pkglib_LTLIBRARIES = libvcl.la - -libvcl_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version - -libvcl_la_SOURCES = \ - vcc_compile.h \ - vcc_token_defs.h \ - \ - vcc_acl.c \ - vcc_action.c \ - vcc_backend.c \ - vcc_backend_util.c \ - vcc_compile.c \ - vcc_expr.c \ - vcc_parse.c \ - vcc_fixed_token.c \ - vcc_obj.c \ - vcc_storage.c \ - vcc_utils.c \ - vcc_symb.c \ - vcc_token.c \ - vcc_var.c \ - vcc_vmod.c \ - vcc_xref.c - -EXTRA_DIST = \ - generate.py - -dist_pkgdata_SCRIPTS = \ - vmodtool.py - -vcc_obj.c vcc_fixed_token.c vcc_token_defs.h: \ - $(srcdir)/generate.py $(top_srcdir)/include/vrt.h - @PYTHON@ $(srcdir)/generate.py $(srcdir) $(top_builddir) - -CLEANFILES = $(builddir)/vcc_token_defs.h \ - $(builddir)/vcc_fixed_token.c \ - $(builddir)/vcc_obj.c diff --git a/lib/libvcl/flint.lnt b/lib/libvcl/flint.lnt deleted file mode 100644 index 60b3850..0000000 --- a/lib/libvcl/flint.lnt +++ /dev/null @@ -1,46 +0,0 @@ --passes=3 - -// Review all below this line - --printf_code( H, void *, unsigned) --printf_code( ju, long long unsigned) --printf_code( jx, long long unsigned) - -+libh ../../config.h --header(../../config.h) --sem(lbv_assert, r_no) --sem(strchr, 1p, type(1), 2n == 0 ? (@p < 1p) : (@p < 1p || @p == 0 )) --sem(vcc_new_source, custodial(1)) - --emacro((???),va_arg) // the va_arg() macro can yield 415, 416, 661, 662 - // 796 and 797 (out-of-bounds errors). - - --emacro(413, offsetof) // likely null pointer - -// -ffc // No automatic custody - --esym(534, vsb_printf) // Ignoring return value of function --esym(534, vsb_cat) // Ignoring return value of function --esym(534, vsb_bcat) // Ignoring return value of function --esym(534, vsb_vprintf) // Ignoring return value of function --esym(534, memset) // Ignoring return value of function --e788 // enum constant 'HND_Unclass' not used within defaulted switch --e716 // while(1) ... --e786 // String concatenation within initializer --e732 // Loss of sign (arg. no. 2) (int to unsigned int) - - --e763 // Redundant declaration for symbol '...' previously declared - - --e737 // Loss of sign in promotion from int to unsigned int --e534 // Ignoring return value of function --e506 // Constant value boolean --e774 // Boolean within 'if' always evaluates to False --e713 // Loss of precision (assignment) (unsigned long long to long long) --e574 // Signed-unsigned mix with relational --e539 // Did not expect positive indentation --e734 // Loss of precision (assignment) (31 bits to 8 bits) --e747 // Significant prototype coercion (arg. no. 2) long --e712 // Loss of precision (assignment) (long long to diff --git a/lib/libvcl/flint.sh b/lib/libvcl/flint.sh deleted file mode 100755 index 3bb465a..0000000 --- a/lib/libvcl/flint.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -flexelint \ - -I/usr/include \ - -I. \ - -I../.. \ - -I../../include \ - -I../../contrib/libevent \ - flint.lnt \ - *.c diff --git a/lib/libvcl/generate.py b/lib/libvcl/generate.py deleted file mode 100755 index 012098a..0000000 --- a/lib/libvcl/generate.py +++ /dev/null @@ -1,952 +0,0 @@ -#!/usr/local/bin/python3.1 -#- -# Copyright (c) 2006 Verdens Gang AS -# Copyright (c) 2006-2013 Varnish Software AS -# All rights reserved. -# -# Author: Poul-Henning Kamp -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# Generate various .c and .h files for the VCL compiler and the interfaces -# for it. - -####################################################################### -# These are our tokens - -# We could drop all words such as "include", "if" etc, and use the -# ID type instead, but declaring them tokens makes them reserved words -# which hopefully makes for better error messages. -# XXX: does it actually do that ? - -import sys - -srcroot = "../.." -buildroot = "../.." -if len(sys.argv) == 3: - srcroot = sys.argv[1] - buildroot = sys.argv[2] - -tokens = { - "T_INC": "++", - "T_DEC": "--", - "T_CAND": "&&", - "T_COR": "||", - "T_LEQ": "<=", - "T_EQ": "==", - "T_NEQ": "!=", - "T_GEQ": ">=", - "T_SHR": ">>", - "T_SHL": "<<", - "T_INCR": "+=", - "T_DECR": "-=", - "T_MUL": "*=", - "T_DIV": "/=", - "T_NOMATCH": "!~", - - # Single char tokens, for convenience on one line - None: "{}()*+-/%><=;!&.|~,", - - # These have handwritten recognizers - "ID": None, - "CNUM": None, - "CSTR": None, - "EOI": None, - "CSRC": None, -} - -####################################################################### -# Our methods and actions - -returns =( - ('recv', "C", ('error', 'pass', 'pipe', 'hash', 'purge',)), - ('pipe', "C", ('error', 'pipe',)), - ('pass', "C", ('error', 'restart', 'fetch',)), - ('hash', "C", ('lookup',)), - ('purge', "C", ('error', 'fetch',)), - ('miss', "C", ('error', 'restart', 'pass', 'fetch',)), - ('hit', "C", ('error', 'restart', 'pass', 'fetch', 'deliver',)), - ('backend_fetch', "B", ('fetch', 'abandon')), - ('backend_response', "B", ('deliver', 'retry', 'abandon')), - ('deliver', "C", ('restart', 'deliver',)), - ('error', "C", ('restart', 'deliver',)), - ('init', "", ('ok',)), - ('fini', "", ('ok',)), -) - -####################################################################### -# Variables available in sessions -# -# 'all' means all methods -# 'client' means all methods tagged "C" -# 'backend' means all methods tagged "B" -# 'both' means all methods tagged "B" or "C" - -sp_variables = [ - ('client.ip', - 'IP', - ( 'both',), - ( ), - ), - ('client.identity', - 'STRING', - ( 'both',), - ( 'both',), - ), - ('server.ip', - 'IP', - ( 'client',), - ( ), - ), - ('server.hostname', - 'STRING', - ( 'client',), - ( ), - ), - ('server.identity', - 'STRING', - ( 'client',), - ( ), - ), - ('server.port', - 'INT', - ( 'client',), - ( ), - ), - ('req.method', - 'STRING', - ( 'client',), - ( 'client',), - ), - ('req.request', - 'STRING', - ( 'client',), - ( 'client',), - ), - ('req.url', - 'STRING', - ( 'client',), - ( 'client',), - ), - ('req.proto', - 'STRING', - ( 'client',), - ( 'client',), - ), - ('req.http.', - 'HEADER', - ( 'client',), - ( 'client',), - ), - ('req.restarts', - 'INT', - ( 'client',), - ( ), - ), - ('req.esi_level', - 'INT', - ( 'client',), - ( ), - ), - ('req.ttl', - 'DURATION', - ( 'client',), - ( 'client',), - ), - ('req.grace', - 'DURATION', - ( 'client',), - ( 'client',), - ), - ('req.keep', - 'DURATION', - ( 'client',), - ( 'client',), - ), - ('req.xid', - 'STRING', - ( 'client',), - ( ), - ), - ('req.esi', - 'BOOL', - ( 'recv', 'backend_response', 'deliver', 'error',), - ( 'recv', 'backend_response', 'deliver', 'error',), - ), - ('req.can_gzip', - 'BOOL', - ( 'client',), - ( ), - ), - ('req.backend', - 'BACKEND', - ( 'client',), - ( 'client',), - ), - ('req.backend.healthy', - 'BOOL', - ( 'client',), - ( ), - ), - ('req.hash_ignore_busy', - 'BOOL', - ( 'recv',), - ( 'recv',), - ), - ('req.hash_always_miss', - 'BOOL', - ( 'recv',), - ( 'recv',), - ), - ('bereq.retries', - 'INT', - ( 'backend',), - ( ), - ), - ('bereq.backend', - 'BACKEND', - ( 'pipe', 'backend', ), - ( 'pipe', 'backend', ), - ), - ('bereq.backend.healthy', - 'BOOL', - ( 'pipe', 'backend', ), - ( ), - ), - ('bereq.method', - 'STRING', - ( 'pipe', 'backend', ), - ( 'pipe', 'backend', ), - ), - ('bereq.request', - 'STRING', - ( 'pipe', 'backend', ), - ( 'pipe', 'backend', ), - ), - ('bereq.url', - 'STRING', - ( 'pipe', 'backend', ), - ( 'pipe', 'backend', ), - ), - ('bereq.proto', - 'STRING', - ( 'pipe', 'backend', ), - ( 'pipe', 'backend', ), - ), - ('bereq.http.', - 'HEADER', - ( 'pipe', 'backend', ), - ( 'pipe', 'backend', ), - ), - ('bereq.uncacheable', - 'BOOL', - ( 'backend', ), - ( 'backend', ), - ), - ('bereq.connect_timeout', - 'DURATION', - ( 'pipe', 'backend', ), - ( 'pipe', 'backend', ), - ), - ('bereq.first_byte_timeout', - 'DURATION', - ( 'pipe', 'backend', ), - ( 'pipe', 'backend', ), - ), - ('bereq.between_bytes_timeout', - 'DURATION', - ( 'pipe', 'backend', ), - ( 'pipe', 'backend', ), - ), - ('beresp.proto', - 'STRING', - ( 'backend_response',), - ( 'backend_response',), - ), - ('beresp.status', - 'INT', - ( 'backend_response',), - ( 'backend_response',), - ), - ('beresp.response', - 'STRING', - ( 'backend_response',), - ( 'backend_response',), - ), - ('beresp.http.', - 'HEADER', - ( 'backend_response',), - ( 'backend_response',), - ), - ('beresp.do_esi', - 'BOOL', - ( 'backend_response',), - ( 'backend_response',), - ), - ('beresp.do_stream', - 'BOOL', - ( 'backend_response',), - ( 'backend_response',), - ), - ('beresp.do_gzip', - 'BOOL', - ( 'backend_response',), - ( 'backend_response',), - ), - ('beresp.do_gunzip', - 'BOOL', - ( 'backend_response',), - ( 'backend_response',), - ), - ('beresp.uncacheable', - 'BOOL', - ( 'backend_response',), - ( 'backend_response',), - ), - ('beresp.ttl', - 'DURATION', - ( 'backend_response',), - ( 'backend_response',), - ), - ('beresp.grace', - 'DURATION', - ( 'backend_response',), - ( 'backend_response',), - ), - ('beresp.keep', - 'DURATION', - ( 'backend_response',), - ( 'backend_response',), - ), - ('beresp.backend.name', - 'STRING', - ( 'backend_response',), - ( ), - ), - ('beresp.backend.ip', - 'IP', - ( 'backend_response',), - ( ), - ), - ('beresp.backend.port', - 'INT', - ( 'backend_response',), - ( ), - ), - ('beresp.storage', - 'STRING', - ( 'backend_response',), - ( 'backend_response',), - ), - ('obj.proto', - 'STRING', - ( 'hit', 'error',), - ( 'hit', 'error',), - ), - ('obj.status', - 'INT', - ( 'error',), - ( 'error',), - ), - ('obj.response', - 'STRING', - ( 'error',), - ( 'error',), - ), - ('obj.hits', - 'INT', - ( 'hit', 'deliver',), - ( 'hit', 'deliver',), - ), - ('obj.http.', - 'HEADER', - ( 'hit', 'error',), - ( 'error',), # XXX ? - ), - ('obj.ttl', - 'DURATION', - ( 'hit', 'error',), - ( 'hit', 'error',), - ), - ('obj.grace', - 'DURATION', - ( 'hit', 'error',), - ( 'hit', 'error',), - ), - ('obj.keep', - 'DURATION', - ( 'hit', 'error',), - ( 'hit', 'error',), - ), - ('obj.last_use', - 'TIME', - ( 'hit', 'deliver',), - ( 'hit', 'deliver',), - ), - ('obj.uncacheable', - 'BOOL', - ( 'hit', 'deliver', 'error',), - ( ), - ), - ('resp.proto', - 'STRING', - ( 'deliver',), - ( 'deliver',), - ), - ('resp.status', - 'INT', - ( 'deliver',), - ( 'deliver',), - ), - ('resp.response', - 'STRING', - ( 'deliver',), - ( 'deliver',), - ), - ('resp.http.', - 'HEADER', - ( 'deliver',), - ( 'deliver',), - ), - ('now', - 'TIME', - ( 'all',), - ( ), - ), -] - -stv_variables = ( - ('free_space', 'BYTES', "0."), - ('used_space', 'BYTES', "0."), - ('happy', 'BOOL', "0"), -) - -####################################################################### -# VCL to C type conversion - -vcltypes = { - 'STRING_LIST': "void*", -} - -fi = open(srcroot + "/include/vrt.h") - -for i in fi: - j = i.split(); - if len(j) < 3: - continue - if j[0] != "typedef": - continue - if j[-1][-1] != ";": - continue - if j[-1][:4] != "VCL_": - continue - d = " ".join(j[1:-1]) - vcltypes[j[-1][4:-1]] = d -fi.close() - -####################################################################### -# Nothing is easily configurable below this line. -####################################################################### - -import sys -import copy - -####################################################################### -# Emit a function to recognize tokens in a string - -def emit_vcl_fixed_token(fo, tokens): - - recog = list() - emit = dict() - for i in tokens: - j = tokens[i] - if (j != None): - recog.append(j) - emit[j] = i - - recog.sort() - rrecog = copy.copy(recog) - rrecog.sort(key = lambda x: -len(x)) - - fo.write(""" -#define M1()\tdo {*q = p + 1; return (p[0]); } while (0) -#define M2(c,t)\tdo {if (p[1] == (c)) { *q = p + 2; return (t); }} while (0) - -unsigned -vcl_fixed_token(const char *p, const char **q) -{ - -\tswitch (p[0]) { -""") - last_initial = None - for i in recog: - if (i[0] == last_initial): - continue - last_initial = i[0] - fo.write("\tcase '%s':\n" % last_initial) - need_ret = True - for j in rrecog: - if (j[0] != last_initial): - continue - if len(j) == 2: - fo.write("\t\tM2('%s', %s);\n" % - (j[1], emit[j])) - elif len(j) == 1: - fo.write("\t\tM1();\n") - need_ret = False - else: - fo.write("\t\tif (") - k = 1 - l = len(j) - while (k < l): - fo.write("p[%d] == '%s'" % (k, j[k])) - fo.write(" &&") - if (k % 3) == 0: - fo.write("\n\t\t ") - else: - fo.write(" ") - k += 1 - fo.write("!isvar(p[%d])) {\n" % l) - fo.write("\t\t\t*q = p + %d;\n" % l) - fo.write("\t\t\treturn (%s);\n" % emit[j]) - fo.write("\t\t}\n") - if need_ret: - fo.write("\t\treturn (0);\n") - fo.write("\tdefault:\n\t\treturn (0);\n\t}\n}\n") - -####################################################################### -# Emit the vcl_tnames (token->string) conversion array - -def emit_vcl_tnames(fo, tokens): - fo.write("\nconst char * const vcl_tnames[256] = {\n") - l = list(tokens.keys()) - l.sort() - for i in l: - j = tokens[i] - if j == None: - j = i - if i[0] == "'": - j = i - fo.write("\t[%s] = \"%s\",\n" % (i, j)) - fo.write("};\n") - -####################################################################### -# Read a C-source file and spit out code that outputs it with VSB_cat() - -def emit_file(fo, fn): - fi = open(fn) - fc = fi.read() - fi.close() - - w = 66 # Width of lines, after white space prefix - maxlen = 10240 # Max length of string literal - - x = 0 - l = 0 - fo.write("\n\t/* %s */\n\n" % fn) - for c in fc: - if l == 0: - fo.write("\tVSB_cat(sb, \"") - l += 12 - x += 12 - if x == 0: - fo.write("\t \"") - d = c - if c == '\n': - d = "\\n" - elif c == '\t': - d = "\\t" - elif c == '"': - d = "\\\"" - elif c == '\\': - d = "\\\\" - - if c == '\n' and x > w - 20: - fo.write(d + "\"\n") - x = 0 - continue - if c.isspace() and x > w - 10: - fo.write(d + "\"\n") - x = 0 - continue - - fo.write(d) - x += len(d) - l += len(d) - if l > maxlen: - fo.write("\");\n") - l = 0; - x = 0 - if x > w - 3: - fo.write("\"\n") - x = 0 - if x != 0: - fo.write("\"") - if l != 0: - fo.write("\t);\n") - -####################################################################### - -def polish_tokens(tokens): - # Expand single char tokens - st = tokens[None] - del tokens[None] - - for i in st: - tokens["'" + i + "'"] = i -####################################################################### - -def file_header(fo): - fo.write("""/* - * NB: This file is machine generated, DO NOT EDIT! - * - * Edit and run generate.py instead - */ -""") - -####################################################################### - -polish_tokens(tokens) - -fo = open(buildroot + "/lib/libvcl/vcc_token_defs.h", "w") - -file_header(fo) - -j = 128 -l = list(tokens.keys()) -l.sort() -for i in l: - if i[0] == "'": - continue - fo.write("#define\t%s %d\n" % (i, j)) - j += 1 - assert j < 256 - -fo.close() - -####################################################################### - -rets = dict() -vcls = list() -vcls_client = list() -vcls_backend = list() -for i in returns: - vcls.append(i[0]) - for j in i[1]: - if j == "B": - vcls_backend.append(i[0]) - elif j == "C": - vcls_client.append(i[0]) - for j in i[2]: - rets[j] = True - -####################################################################### - -fo = open(buildroot + "/include/tbl/vcl_returns.h", "w") - -file_header(fo) - -fo.write("\n/*lint -save -e525 -e539 */\n") - -fo.write("\n#ifdef VCL_RET_MAC\n") -l = list(rets.keys()) -l.sort() -for i in l: - fo.write("VCL_RET_MAC(%s, %s" % (i.lower(), i.upper())) - s=", " - for j in returns: - if i in j[2]: - fo.write("%sVCL_MET_%s" % (s, j[0].upper())) - s = " | " - fo.write(")\n") -fo.write("#endif\n") - -fo.write("\n#ifdef VCL_MET_MAC\n") -for i in returns: - fo.write("VCL_MET_MAC(%s,%s,\n" % (i[0].lower(), i[0].upper())) - p = " (" - for j in i[2]: - fo.write(" %s(1U << VCL_RET_%s)\n" % (p, j.upper())) - p = "| " - fo.write("))\n") -fo.write("#endif\n") -fo.write("\n/*lint -restore */\n") -fo.close() - -####################################################################### - -fo = open(buildroot + "/include/vcl.h", "w") - -file_header(fo) - -fo.write(""" -struct vrt_ctx; -struct req; -struct busyobj; -struct ws; -struct cli; -struct worker; - -typedef int vcl_init_f(struct cli *); -typedef void vcl_fini_f(struct cli *); -typedef int vcl_func_f(const struct vrt_ctx *ctx); -""") - - -fo.write("\n/* VCL Methods */\n") -n = 0 -for i in returns: - fo.write("#define VCL_MET_%s\t\t(1U << %d)\n" % (i[0].upper(), n)) - n += 1 - -fo.write("\n#define VCL_MET_MAX\t\t%d\n" % n) -fo.write("\n#define VCL_MET_MASK\t\t0x%x\n" % ((1 << n) - 1)) - - -fo.write("\n/* VCL Returns */\n") -n = 0 -l = list(rets.keys()) -l.sort() -for i in l: - fo.write("#define VCL_RET_%s\t\t%d\n" % (i.upper(), n)) - n += 1 - -fo.write("\n#define VCL_RET_MAX\t\t%d\n" % n) - - -fo.write(""" -struct VCL_conf { - unsigned magic; -#define VCL_CONF_MAGIC 0x7406c509 /* from /dev/random */ - - struct director **director; - unsigned ndirector; - struct vrt_ref *ref; - unsigned nref; - unsigned busy; - unsigned discard; - - unsigned nsrc; - const char **srcname; - const char **srcbody; - - vcl_init_f *init_vcl; - vcl_fini_f *fini_vcl; -""") - -for i in returns: - fo.write("\tvcl_func_f\t*" + i[0] + "_func;\n") - -fo.write(""" -}; -""") - -fo.close() - -####################################################################### - -def restrict(fo, spec): - d = dict() - for j in spec: - if j == 'all': - for i in vcls: - d[i] = True - elif j == 'backend': - for i in vcls_backend: - d[i] = True - elif j == 'client': - for i in vcls_client: - d[i] = True - elif j == 'both': - for i in vcls_client: - d[i] = True - for i in vcls_backend: - d[i] = True - else: - assert j in vcls - d[j] = True - p = "" - n = 0 - l = list(d.keys()) - l.sort() - w = 0 - fo.write("\t\t") - for j in l: - x = p + "VCL_MET_" + j.upper() - if w + len(x) > 60: - fo.write("\n\t\t") - w = 0 - fo.write(x) - w += len(x) - p = " | " - if len(d) == 0: - fo.write("0") - fo.write(",\n") - -####################################################################### - -fh = open(buildroot + "/include/vrt_obj.h", "w") -file_header(fh) - -fo = open(buildroot + "/lib/libvcl/vcc_obj.c", "w") -file_header(fo) - -fo.write(""" -#include "config.h" - -#include - -#include "vcc_compile.h" - -const struct var vcc_vars[] = { -""") - -sp_variables.sort() -for i in sp_variables: - typ = i[1] - cnam = i[0].replace(".", "_") - ctyp = vcltypes[typ] - - fo.write("\t{ \"%s\", %s, %d,\n" % (i[0], typ, len(i[0]))) - - if len(i[2]) == 0: - fo.write('\t NULL,\t/* No reads allowed */\n') - elif typ == "HEADER": - fo.write('\t "HDR_') - fo.write(i[0].split(".")[0].upper()) - fo.write('",\n') - else: - fo.write('\t "VRT_r_%s(ctx)",\n' % cnam) - fh.write(ctyp + " VRT_r_%s(const struct vrt_ctx *);\n" % cnam ) - restrict(fo, i[2]) - - if len(i[3]) == 0: - fo.write('\t NULL,\t/* No writes allowed */\n') - elif typ == "HEADER": - fo.write('\t "HDR_') - fo.write(i[0].split(".")[0].upper()) - fo.write('",\n') - else: - fo.write('\t "VRT_l_%s(ctx, ",\n' % cnam) - fh.write("void VRT_l_%s(const struct vrt_ctx *, " % cnam) - if typ != "STRING": - fh.write(ctyp + ");\n") - else: - fh.write(ctyp + ", ...);\n") - restrict(fo, i[3]) - - fo.write("\t},\n") - -fo.write("\t{ NULL }\n};\n") - -for i in stv_variables: - fh.write(vcltypes[i[1]] + " VRT_Stv_" + i[0] + "(const char *);\n") - -fo.close() -fh.close() - -####################################################################### - -fo = open(buildroot + "/lib/libvcl/vcc_fixed_token.c", "w") - -file_header(fo) -fo.write(""" - -#include "config.h" - -#include -#include - -#include "vcc_compile.h" -""") - -emit_vcl_fixed_token(fo, tokens) -emit_vcl_tnames(fo, tokens) - -fo.write(""" -void -vcl_output_lang_h(struct vsb *sb) -{ -""") - -emit_file(fo, buildroot + "/include/vcl.h") -emit_file(fo, srcroot + "/include/vrt.h") -emit_file(fo, buildroot + "/include/vrt_obj.h") - -fo.write(""" -} -""") - -fo.close() - -####################################################################### -ft = open(buildroot + "/include/tbl/vcc_types.h", "w") -file_header(ft) - -ft.write("/*lint -save -e525 -e539 */\n") - -i = list(vcltypes.keys()) -i.sort() -for j in i: - ft.write("VCC_TYPE(" + j + ")\n") -ft.write("/*lint -restore */\n") -ft.close() - -####################################################################### - -fo = open(buildroot + "/include/tbl/vrt_stv_var.h", "w") - -file_header(fo) - -fo.write(""" -#ifndef VRTSTVTYPE -#define VRTSTVTYPE(ct) -#define VRTSTVTYPEX -#endif -#ifndef VRTSTVVAR -#define VRTSTVVAR(nm, vtype, ctype, dval) -#define VRTSTVVARX -#endif -""") - -x=dict() -for i in stv_variables: - ct = vcltypes[i[1]] - if not ct in x: - fo.write("VRTSTVTYPE(" + ct + ")\n") - x[ct] = 1 - fo.write("VRTSTVVAR(" + i[0] + ",\t" + i[1] + ",\t") - fo.write(ct + ",\t" + i[2] + ")") - fo.write("\n") - -fo.write(""" -#ifdef VRTSTVTYPEX -#undef VRTSTVTYPEX -#undef VRTSTVTYPE -#endif -#ifdef VRTSTVVARX -#undef VRTSTVVARX -#undef VRTSTVVAR -#endif -""") - -fo.close diff --git a/lib/libvcl/vcc_acl.c b/lib/libvcl/vcc_acl.c deleted file mode 100644 index fa8a7d7..0000000 --- a/lib/libvcl/vcc_acl.c +++ /dev/null @@ -1,502 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2010 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include -#include - -#include - -#include -#include -#include -#include - -#include "vcc_compile.h" - -#include "vrt.h" - -struct acl_e { - VTAILQ_ENTRY(acl_e) list; - unsigned char data[VRT_ACL_MAXADDR + 1]; - unsigned mask; - unsigned not; - unsigned para; - struct token *t_addr; - struct token *t_mask; -}; - -/* Compare two acl rules for ordering */ - -#define CMP(a, b) \ - do { \ - if ((a) < (b)) \ - return (-1); \ - else if ((b) < (a)) \ - return (1); \ - } while (0) - -static int -vcl_acl_cmp(struct acl_e *ae1, struct acl_e *ae2) -{ - unsigned char *p1, *p2; - unsigned m; - - p1 = ae1->data; - p2 = ae2->data; - m = ae1->mask; - if (ae2->mask < m) - m = ae2->mask; - for (; m >= 8; m -= 8) { - CMP(*p1, *p2); - p1++; - p2++; - } - if (m) { - m = 0xff00 >> m; - m &= 0xff; - CMP(*p1 & m, *p2 & m); - } - /* Long mask is less than short mask */ - CMP(ae2->mask, ae1->mask); - - return (0); -} - - -static void -vcc_acl_add_entry(struct vcc *tl, const struct acl_e *ae, int l, - const unsigned char *u, int fam) -{ - struct acl_e *ae2, *aen; - int i; - - if (fam == PF_INET && ae->mask > 32) { - VSB_printf(tl->sb, - "Too wide mask (%u) for IPv4 address\n", ae->mask); - if (ae->t_mask != NULL) - vcc_ErrWhere(tl, ae->t_mask); - else - vcc_ErrWhere(tl, ae->t_addr); - return; - } - if (fam == PF_INET6 && ae->mask > 128) { - VSB_printf(tl->sb, - "Too wide mask (%u) for IPv6 address\n", ae->mask); - vcc_ErrWhere(tl, ae->t_mask); - return; - } - - /* Make a copy from the template */ - aen = TlAlloc(tl, sizeof *ae2); - AN(aen); - *aen = *ae; - - /* We treat family as part of address, it saves code */ - assert(fam <= 0xff); - aen->data[0] = fam & 0xff; - aen->mask += 8; - - memcpy(aen->data + 1, u, l); - - VTAILQ_FOREACH(ae2, &tl->acl, list) { - i = vcl_acl_cmp(aen, ae2); - if (i == 0) { - /* - * If the two rules agree, silently ignore it - * XXX: is that counter intuitive ? - */ - if (aen->not == ae2->not) - return; - VSB_printf(tl->sb, "Conflicting ACL entries:\n"); - vcc_ErrWhere(tl, ae2->t_addr); - VSB_printf(tl->sb, "vs:\n"); - vcc_ErrWhere(tl, aen->t_addr); - return; - } - /* - * We could eliminate pointless rules here, for instance in: - * "10.1.0.1"; - * "10.1"; - * The first rule is clearly pointless, as the second one - * covers it. - * - * We do not do this however, because the shmlog may - * be used to gather statistics. - */ - if (i < 0) { - VTAILQ_INSERT_BEFORE(ae2, aen, list); - return; - } - } - VTAILQ_INSERT_TAIL(&tl->acl, aen, list); -} - -static void -vcc_acl_try_getaddrinfo(struct vcc *tl, struct acl_e *ae) -{ - struct addrinfo *res0, *res, hint; - struct sockaddr_in *sin4; - struct sockaddr_in6 *sin6; - unsigned char *u, i4, i6; - int error; - - memset(&hint, 0, sizeof hint); - hint.ai_family = PF_UNSPEC; - hint.ai_socktype = SOCK_STREAM; - error = getaddrinfo(ae->t_addr->dec, "0", &hint, &res0); - if (error) { - if (ae->para) { - VSB_printf(tl->sb, - "Warning: %s ignored\n -- %s\n", - ae->t_addr->dec, gai_strerror(error)); - Fh(tl, 1, "/* Ignored ACL entry: %s%s", - ae->para ? "\"(\" " : "", ae->not ? "\"!\" " : ""); - EncToken(tl->fh, ae->t_addr); - if (ae->t_mask) - Fh(tl, 0, "/%u", ae->mask); - Fh(tl, 0, "%s\n", ae->para ? " \")\"" : ""); - Fh(tl, 1, " * getaddrinfo: %s */\n", - gai_strerror(error)); - } else { - VSB_printf(tl->sb, - "DNS lookup(%s): %s\n", - ae->t_addr->dec, gai_strerror(error)); - vcc_ErrWhere(tl, ae->t_addr); - } - return; - } - - i4 = i6 = 0; - for(res = res0; res != NULL; res = res->ai_next) { - switch(res->ai_family) { - case PF_INET: - assert(PF_INET < 256); - sin4 = (void*)res->ai_addr; - assert(sizeof(sin4->sin_addr) == 4); - u = (void*)&sin4->sin_addr; - if (ae->t_mask == NULL) - ae->mask = 32; - i4++; - vcc_acl_add_entry(tl, ae, 4, u, res->ai_family); - break; - case PF_INET6: - assert(PF_INET6 < 256); - sin6 = (void*)res->ai_addr; - assert(sizeof(sin6->sin6_addr) == 16); - u = (void*)&sin6->sin6_addr; - if (ae->t_mask == NULL) - ae->mask = 128; - i6++; - vcc_acl_add_entry(tl, ae, 16, u, res->ai_family); - break; - default: - VSB_printf(tl->sb, - "Ignoring unknown protocol family (%d) for %.*s\n", - res->ai_family, PF(ae->t_addr)); - continue; - } - ERRCHK(tl); - } - freeaddrinfo(res0); - - if (ae->t_mask != NULL && i4 > 0 && i6 > 0) { - VSB_printf(tl->sb, - "Mask (%u) specified, but string resolves to" - " both IPv4 and IPv6 addresses.\n", ae->mask); - vcc_ErrWhere(tl, ae->t_mask); - return; - } -} - -/*-------------------------------------------------------------------- - * Ancient stupidity on the part of X/Open and other standards orgs - * dictate that "192.168" be translated to 192.0.0.168. Ever since - * CIDR happened, "192.168/16" notation has been used, but appearantly - * no API supports parsing this, so roll our own. - */ - -static int -vcc_acl_try_netnotation(struct vcc *tl, struct acl_e *ae) -{ - unsigned char b[4]; - int i, j, k; - unsigned u; - const char *p; - - memset(b, 0, sizeof b); - p = ae->t_addr->dec; - for (i = 0; i < 4; i++) { - j = sscanf(p, "%u%n", &u, &k); - if (j != 1) - return (0); - if (u & ~0xff) - return (0); - b[i] = (unsigned char)u; - if (p[k] == '\0') - break; - if (p[k] != '.') - return (0); - p += k + 1; - } - if (ae->t_mask == NULL) - ae->mask = 8 + 8 * i; - vcc_acl_add_entry(tl, ae, 4, b, AF_INET); - return (1); -} - -static void -vcc_acl_entry(struct vcc *tl) -{ - struct acl_e *ae; - - ae = TlAlloc(tl, sizeof *ae); - AN(ae); - - if (tl->t->tok == '!') { - ae->not = 1; - vcc_NextToken(tl); - } - - if (tl->t->tok == '(') { - ae->para = 1; - vcc_NextToken(tl); - } - - if (!ae->not && tl->t->tok == '!') { - ae->not = 1; - vcc_NextToken(tl); - } - - ExpectErr(tl, CSTR); - ae->t_addr = tl->t; - vcc_NextToken(tl); - - if (tl->t->tok == '/') { - vcc_NextToken(tl); - ae->t_mask = tl->t; - ExpectErr(tl, CNUM); - ae->mask = vcc_UintVal(tl); - } - - if (ae->para) - SkipToken(tl, ')'); - - if (!vcc_acl_try_netnotation(tl, ae)) { - ERRCHK(tl); - vcc_acl_try_getaddrinfo(tl, ae); - } - ERRCHK(tl); -} - -/********************************************************************* - * Emit a function to match the ACL we have collected - */ - -/* - * XXX: this is semi-silly. We try really hard to not depend in the - * XXX: systems include files while compiling VCL, but we need to know - * XXX: the size of the sa_familiy member. - * XXX: FlexeLint complains about these antics, so isolate it in a - * XXX: separate function. - */ - -/*lint -save -e506 -e774 -e550 */ -static void -c_is_a_silly_language(const struct vcc *tl) -{ - struct sockaddr sa; - - assert(sizeof (unsigned char) == 1); - assert(sizeof (unsigned short) == 2); - assert(sizeof (unsigned int) == 4); - if (sizeof sa.sa_family == 1) - Fh(tl, 0, "\tunsigned char fam;\n"); - else if (sizeof sa.sa_family == 2) - Fh(tl, 0, "\tunsigned short fam;\n"); - else if (sizeof sa.sa_family == 4) - Fh(tl, 0, "\tunsigned int fam;\n"); - else - assert(0 == __LINE__); -} -/*lint -restore */ - -static void -vcc_acl_emit(const struct vcc *tl, const char *acln, int anon) -{ - struct acl_e *ae; - int depth, l, m, i; - unsigned at[VRT_ACL_MAXADDR + 1]; - const char *oc; - - Fh(tl, 0, "\nstatic int\n"); - Fh(tl, 0, "match_acl_%s_%s(const struct vrt_ctx *ctx, const void *p)\n", - anon ? "anon" : "named", acln); - Fh(tl, 0, "{\n"); - Fh(tl, 0, "\tconst unsigned char *a;\n"); - c_is_a_silly_language(tl); - - Fh(tl, 0, "\n"); - Fh(tl, 0, "\ta = p;\n"); - Fh(tl, 0, "\tVRT_memmove(&fam, a + %zd, sizeof fam);\n", - offsetof(struct sockaddr, sa_family)); - Fh(tl, 0, "\tif (fam == %d)\n", PF_INET); - Fh(tl, 0, "\t\ta += %zd;\n", offsetof(struct sockaddr_in, sin_addr)); - Fh(tl, 0, "\telse if (fam == %d)\n", PF_INET6); - Fh(tl, 0, "\t\ta += %zd;\n", offsetof(struct sockaddr_in6, sin6_addr)); - Fh(tl, 0, "\telse {\n"); - Fh(tl, 0, "\t\tVRT_acl_log(ctx, \"NO_FAM %s\");\n", acln); - Fh(tl, 0, "\t\treturn(0);\n"); - Fh(tl, 0, "\t}\n\n"); - depth = -1; - oc = 0; - at[0] = 256; - VTAILQ_FOREACH(ae, &tl->acl, list) { - - /* Find how much common prefix we have */ - for (l = 0; l <= depth && l * 8 < ae->mask - 7; l++) { - assert(l >= 0); - if (ae->data[l] != at[l]) - break; - } - - /* Back down, if necessary */ - oc = ""; - while (l <= depth) { - Fh(tl, 0, "\t%*s}\n", -depth, ""); - depth--; - } - - m = ae->mask; - m -= l * 8; - assert(m >= 0); - - /* Do whole byte compares */ - for (i = l; m >= 8; m -= 8, i++) { - if (i == 0) - Fh(tl, 0, "\t%*s%sif (fam == %d) {\n", - -i, "", oc, ae->data[i]); - else - Fh(tl, 0, "\t%*s%sif (a[%d] == %d) {\n", - -i, "", oc, i - 1, ae->data[i]); - at[i] = ae->data[i]; - depth = i; - oc = ""; - } - - if (m > 0) { - /* Do fractional byte compares */ - Fh(tl, 0, "\t%*s%sif ((a[%d] & 0x%x) == %d) {\n", - -i, "", oc, i - 1, (0xff00 >> m) & 0xff, - ae->data[i] & ((0xff00 >> m) & 0xff)); - at[i] = 256; - depth = i; - oc = ""; - } - - i = (ae->mask + 7) / 8; - - if (!anon) { - Fh(tl, 0, "\t%*sVRT_acl_log(ctx, \"%sMATCH %s \" ", - -i, "", ae->not ? "NEG_" : "", acln); - EncToken(tl->fh, ae->t_addr); - if (ae->t_mask != NULL) - Fh(tl, 0, " \"/%.*s\" ", PF(ae->t_mask)); - Fh(tl, 0, ");\n"); - } - - Fh(tl, 0, "\t%*sreturn (%d);\n", -i, "", ae->not ? 0 : 1); - } - - /* Unwind */ - for (; 0 <= depth; depth--) - Fh(tl, 0, "\t%*.*s}\n", depth, depth, ""); - - /* Deny by default */ - if (!anon) - Fh(tl, 0, "\tVRT_acl_log(ctx, \"NO_MATCH %s\");\n", acln); - Fh(tl, 0, "\treturn (0);\n}\n"); -} - -void -vcc_Acl_Hack(struct vcc *tl, char *b) -{ - char acln[32]; - unsigned tcond; - - VTAILQ_INIT(&tl->acl); - tcond = tl->t->tok; - vcc_NextToken(tl); - bprintf(acln, "%u", tl->unique++); - vcc_acl_entry(tl); - vcc_acl_emit(tl, acln, 1); - sprintf(b, "%smatch_acl_anon_%s(ctx, \v1)", - (tcond == T_NEQ ? "!" : ""), acln); -} - -void -vcc_Acl(struct vcc *tl) -{ - struct token *an; - int i; - char acln[1024]; - - vcc_NextToken(tl); - VTAILQ_INIT(&tl->acl); - - ExpectErr(tl, ID); - if (!vcc_isCid(tl->t)) { - VSB_printf(tl->sb, - "Names of VCL acl's cannot contain '-'\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - an = tl->t; - vcc_NextToken(tl); - - i = vcc_AddDef(tl, an, SYM_ACL); - if (i > 1) { - VSB_printf(tl->sb, "ACL %.*s redefined\n", PF(an)); - vcc_ErrWhere(tl, an); - return; - } - bprintf(acln, "%.*s", PF(an)); - - SkipToken(tl, '{'); - - while (tl->t->tok != '}') { - vcc_acl_entry(tl); - ERRCHK(tl); - SkipToken(tl, ';'); - } - SkipToken(tl, '}'); - - vcc_acl_emit(tl, acln, 0); -} diff --git a/lib/libvcl/vcc_action.c b/lib/libvcl/vcc_action.c deleted file mode 100644 index 4e441d2..0000000 --- a/lib/libvcl/vcc_action.c +++ /dev/null @@ -1,445 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file parses the real action of the VCL code, the procedure - * statements which do the actual work. - */ - -#include "config.h" - -#include - -#include "vcc_compile.h" - -/*--------------------------------------------------------------------*/ - -static void -parse_call(struct vcc *tl) -{ - - vcc_NextToken(tl); - ExpectErr(tl, ID); - vcc_AddCall(tl, tl->t); - vcc_AddRef(tl, tl->t, SYM_SUB); - Fb(tl, 1, "if (VGC_function_%.*s(ctx))\n", PF(tl->t)); - Fb(tl, 1, "\treturn (1);\n"); - vcc_NextToken(tl); - return; -} - -/*--------------------------------------------------------------------*/ - -static void -parse_error(struct vcc *tl) -{ - - VSB_printf(tl->sb, - "Syntax has changed, use:\n" - "\treturn(error(999));\n" - "or\n" - "\treturn(error(999, \"Response text\"));\n"); - vcc_ErrWhere(tl, tl->t); - return; -} - -/*--------------------------------------------------------------------*/ - -static const struct arith { - enum var_type type; - unsigned oper; - enum var_type want; -} arith[] = { - { INT, T_INCR, INT }, - { INT, T_DECR, INT }, - { INT, T_MUL, INT }, - { INT, T_DIV, INT }, - { INT, '=', INT }, - { INT, 0, INT }, - { TIME, T_INCR, DURATION }, - { TIME, T_DECR, DURATION }, - { TIME, T_MUL, REAL }, - { TIME, T_DIV, REAL }, - { TIME, '=', TIME }, - { TIME, 0, TIME }, - { DURATION, T_INCR, DURATION }, - { DURATION, T_DECR, DURATION }, - { DURATION, T_MUL, REAL }, - { DURATION, T_DIV, REAL }, - { DURATION, '=', DURATION }, - { DURATION, 0, DURATION }, - { VOID, '=', VOID } -}; - -static void -parse_set(struct vcc *tl) -{ - const struct var *vp; - const struct arith *ap; - enum var_type fmt; - - vcc_NextToken(tl); - ExpectErr(tl, ID); - vp = vcc_FindVar(tl, tl->t, 1, "cannot be set"); - ERRCHK(tl); - assert(vp != NULL); - Fb(tl, 1, "%s\n", vp->lname); - tl->indent += INDENT; - vcc_NextToken(tl); - fmt = vp->fmt; - for (ap = arith; ap->type != VOID; ap++) { - if (ap->type != fmt) - continue; - if (ap->oper != tl->t->tok) - continue; - if (ap->oper != '=') - Fb(tl, 1, "%s %c ", vp->rname, *tl->t->b); - vcc_NextToken(tl); - fmt = ap->want; - break; - } - if (ap->type == VOID) - SkipToken(tl, ap->oper); - if (fmt == HEADER) { - vcc_Expr(tl, STRING_LIST); - } else if (fmt == STRING) { - vcc_Expr(tl, STRING_LIST); - } else { - vcc_Expr(tl, fmt); - } - tl->indent -= INDENT; - Fb(tl, 1, ");\n"); -} - -/*--------------------------------------------------------------------*/ - -static void -parse_unset(struct vcc *tl) -{ - const struct var *vp; - - /* XXX: Wrong, should use VCC_Expr(HEADER) */ - vcc_NextToken(tl); - ExpectErr(tl, ID); - vp = vcc_FindVar(tl, tl->t, 1, "cannot be unset"); - ERRCHK(tl); - assert(vp != NULL); - if (vp->fmt != HEADER) { - VSB_printf(tl->sb, - "Only http header variables can be unset.\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - ERRCHK(tl); - Fb(tl, 1, "%svrt_magic_string_unset);\n", vp->lname); - vcc_NextToken(tl); -} - -/*--------------------------------------------------------------------*/ - -static void -parse_new(struct vcc *tl) -{ - struct symbol *sy1, *sy2, *sy3; - const char *p, *s_obj, *s_init, *s_struct, *s_fini; - char buf1[128]; - char buf2[128]; - - vcc_NextToken(tl); - ExpectErr(tl, ID); - if (!vcc_isCid(tl->t)) { - VSB_printf(tl->sb, - "Names of VCL objects cannot contain '-'\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - sy1 = VCC_FindSymbol(tl, tl->t, SYM_NONE); - XXXAZ(sy1); - - sy1 = VCC_AddSymbolTok(tl, tl->t, SYM_NONE); // XXX: NONE ? - XXXAN(sy1); - vcc_NextToken(tl); - - ExpectErr(tl, '='); - vcc_NextToken(tl); - - ExpectErr(tl, ID); - sy2 = VCC_FindSymbol(tl, tl->t, SYM_OBJECT); - XXXAN(sy2); - - /*lint -save -e448 */ - /* Split the first three args */ - p = sy2->args; - s_obj = p; - p += strlen(p) + 1; - s_init = p; - while (p[0] != '\0' || p[1] != '\0') - p++; - p += 2; - s_struct = p; - p += strlen(p) + 1; - s_fini = p + strlen(p) + 1; - while (p[0] != '\0' || p[1] != '\0') - p++; - p += 2; - - Fh(tl, 0, "static %s *%s;\n\n", s_struct, sy1->name); - - vcc_NextToken(tl); - - bprintf(buf1, ", &%s, \"%s\"", sy1->name, sy1->name); - vcc_Eval_Func(tl, s_init, buf1, "ASDF", s_init + strlen(s_init) + 1); - Fd(tl, 0, "\t%s(&%s);\n", s_fini, sy1->name); - ExpectErr(tl, ';'); - - bprintf(buf1, ", %s", sy1->name); - /* Split the methods from the args */ - while (*p != '\0') { - p += strlen(s_obj); - bprintf(buf2, "%s%s", sy1->name, p); - sy3 = VCC_AddSymbolStr(tl, buf2, SYM_FUNC); - AN(sy3); - sy3->eval = vcc_Eval_SymFunc; - p += strlen(p) + 1; - sy3->cfunc = p; - p += strlen(p) + 1; - - /* Functions which return VOID are procedures */ - if (!memcmp(p, "VOID\0", 5)) - sy3->kind = SYM_PROC; - - sy3->args = p; - sy3->extra = TlDup(tl, buf1); - while (p[0] != '\0' || p[1] != '\0') { - if (!memcmp(p, "ENUM\0", 5)) { - /* XXX: Special case for ENUM that has - it's own \0\0 end marker. Not exactly - elegant, we should consider - alternatives here. Maybe runlength - encode the entire block? */ - p += strlen(p) + 1; - while (p[0] != '\0' || p[1] != '\0') - p++; - } - p++; - } - p += 2; - } - /*lint -restore */ -} - -/*--------------------------------------------------------------------*/ - -static void -parse_ban(struct vcc *tl) -{ - - vcc_NextToken(tl); - - ExpectErr(tl, '('); - vcc_NextToken(tl); - - Fb(tl, 1, "VRT_ban_string(\n"); - tl->indent += INDENT; - vcc_Expr(tl, STRING); - tl->indent -= INDENT; - ERRCHK(tl); - Fb(tl, 1, ");\n"); - - ExpectErr(tl, ')'); - vcc_NextToken(tl); -} - -/*--------------------------------------------------------------------*/ - -static void -parse_hash_data(struct vcc *tl) -{ - vcc_NextToken(tl); - SkipToken(tl, '('); - - Fb(tl, 1, "VRT_hashdata(ctx, "); - vcc_Expr(tl, STRING_LIST); - ERRCHK(tl); - Fb(tl, 0, ");\n"); - SkipToken(tl, ')'); -} - -/*--------------------------------------------------------------------*/ - -static void -parse_return(struct vcc *tl) -{ - int retval = 0; - - vcc_NextToken(tl); - ExpectErr(tl, '('); - vcc_NextToken(tl); - ExpectErr(tl, ID); - - /* 'error' gets special handling, to allow optional status/response */ - if (vcc_IdIs(tl->t, "error")) { - vcc_NextToken(tl); - if (tl->t->tok == ')') { - VSB_printf(tl->sb, - "Syntax has changed, use:\n" - "\treturn(error(999));\n" - "or\n" - "\treturn(error(999, \"Response text\"));\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - ExpectErr(tl, '('); - vcc_NextToken(tl); - Fb(tl, 1, "VRT_error(ctx,\n"); - tl->indent += INDENT; - vcc_Expr(tl, INT); - ERRCHK(tl); - Fb(tl, 1, ",\n"); - if (tl->t->tok == ',') { - vcc_NextToken(tl); - vcc_Expr(tl, STRING); - ERRCHK(tl); - } else { - Fb(tl, 1, "(const char*)0\n"); - } - tl->indent -= INDENT; - ExpectErr(tl, ')'); - vcc_NextToken(tl); - Fb(tl, 1, ");\n"); - Fb(tl, 1, "VRT_handling(ctx, VCL_RET_ERROR);\n"); - Fb(tl, 1, "return (1);\n"); - vcc_ProcAction(tl->curproc, VCL_RET_ERROR, tl->t); - ExpectErr(tl, ')'); - vcc_NextToken(tl); - return; - } - -#define VCL_RET_MAC(l, U, B) \ - do { \ - if (vcc_IdIs(tl->t, #l)) { \ - Fb(tl, 1, "VRT_handling(ctx, VCL_RET_" #U ");\n"); \ - Fb(tl, 1, "return (1);\n"); \ - vcc_ProcAction(tl->curproc, VCL_RET_##U, tl->t);\ - retval = 1; \ - } \ - } while (0); -#include "tbl/vcl_returns.h" -#undef VCL_RET_MAC - if (!retval) { - VSB_printf(tl->sb, "Expected return action name.\n"); - vcc_ErrWhere(tl, tl->t); - ERRCHK(tl); - } - vcc_NextToken(tl); - ExpectErr(tl, ')'); - vcc_NextToken(tl); -} - -/*--------------------------------------------------------------------*/ - -static void -parse_rollback(struct vcc *tl) -{ - - vcc_NextToken(tl); - Fb(tl, 1, "VRT_Rollback(ctx);\n"); -} - -/*--------------------------------------------------------------------*/ - -static void -parse_purge(struct vcc *tl) -{ - - vcc_NextToken(tl); - Fb(tl, 1, "VRT_purge(ctx, 0, 0);\n"); -} - -/*--------------------------------------------------------------------*/ - -static void -parse_synthetic(struct vcc *tl) -{ - vcc_NextToken(tl); - - Fb(tl, 1, "VRT_synth_page(ctx, 0, "); - vcc_Expr(tl, STRING_LIST); - ERRCHK(tl); - Fb(tl, 0, ");\n"); -} - -/*--------------------------------------------------------------------*/ - -typedef void action_f(struct vcc *tl); - -static struct action_table { - const char *name; - action_f *func; - unsigned bitmask; -} action_table[] = { - /* Keep list sorted from here */ - { "ban", parse_ban }, - { "call", parse_call }, - { "error", parse_error }, - { "hash_data", parse_hash_data, VCL_MET_HASH }, - { "new", parse_new, VCL_MET_INIT}, - { "purge", parse_purge, VCL_MET_MISS | VCL_MET_HIT }, - { "remove", parse_unset }, /* backward compatibility */ - { "return", parse_return }, - { "rollback", parse_rollback }, - { "set", parse_set }, - { "synthetic", parse_synthetic, VCL_MET_ERROR }, - { "unset", parse_unset }, - { NULL, NULL } -}; - -int -vcc_ParseAction(struct vcc *tl) -{ - struct token *at; - struct action_table *atp; - const struct symbol *sym; - - at = tl->t; - assert(at->tok == ID); - for(atp = action_table; atp->name != NULL; atp++) { - if (vcc_IdIs(at, atp->name)) { - if (atp->bitmask != 0) - vcc_AddUses(tl, at, atp->bitmask, - "not a valid action"); - atp->func(tl); - return (1); - } - } - sym = VCC_FindSymbol(tl, tl->t, SYM_NONE); - if (sym != NULL && sym->kind == SYM_PROC) { - vcc_Expr_Call(tl, sym); - return (1); - } - return (0); -} diff --git a/lib/libvcl/vcc_backend.c b/lib/libvcl/vcc_backend.c deleted file mode 100644 index b548d94..0000000 --- a/lib/libvcl/vcc_backend.c +++ /dev/null @@ -1,484 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include "config.h" - -#include -#include - -#include "vcc_compile.h" - -#include "vss.h" - -/*-------------------------------------------------------------------- - * Struct sockaddr is not really designed to be a compile time - * initialized data structure, so we encode it as a byte-string - * and put it in an official sockaddr when we load the VCL. - */ - -static void -Emit_Sockaddr(struct vcc *tl, const struct token *t_host, const char *port) -{ - const char *ipv4, *ipv4a, *ipv6, *ipv6a, *pa; - const char *err; - char *hop, *pop; - - AN(t_host->dec); - - err = VSS_parse(t_host->dec, &hop, &pop); - if (err != NULL) { - VSB_printf(tl->sb, - "Backend host '%.*s': %s\n", PF(t_host), err); - vcc_ErrWhere(tl, t_host); - return; - } - Resolve_Sockaddr(tl, - hop != NULL ? hop : t_host->dec, - pop != NULL ? pop : port, - &ipv4, &ipv4a, &ipv6, &ipv6a, &pa, 2, t_host, "Backend host"); - ERRCHK(tl); - if (ipv4 != NULL) { - Fb(tl, 0, "\t.ipv4_sockaddr = %s,\n", ipv4); - Fb(tl, 0, "\t.ipv4_addr = \"%s\",\n", ipv4a); - } - if (ipv6 != NULL) { - Fb(tl, 0, "\t.ipv6_sockaddr = %s,\n", ipv6); - Fb(tl, 0, "\t.ipv6_addr = \"%s\",\n", ipv6a); - } - Fb(tl, 0, "\t.port = \"%s\",\n", pa); -} - -/*-------------------------------------------------------------------- - * Parse a backend probe specification - */ - -static void -vcc_ProbeRedef(struct vcc *tl, struct token **t_did, - struct token *t_field) -{ - /* .url and .request are mutually exclusive */ - - if (*t_did != NULL) { - VSB_printf(tl->sb, "Probe request redefinition at:\n"); - vcc_ErrWhere(tl, t_field); - VSB_printf(tl->sb, "Previous definition:\n"); - vcc_ErrWhere(tl, *t_did); - return; - } - *t_did = t_field; -} - -static void -vcc_ParseProbeSpec(struct vcc *tl) -{ - struct fld_spec *fs; - struct token *t_field; - struct token *t_did = NULL, *t_window = NULL, *t_threshold = NULL; - struct token *t_initial = NULL; - unsigned window, threshold, initial, status; - double t; - - fs = vcc_FldSpec(tl, - "?url", - "?request", - "?expected_response", - "?timeout", - "?interval", - "?window", - "?threshold", - "?initial", - NULL); - - SkipToken(tl, '{'); - - window = 0; - threshold = 0; - initial = 0; - status = 0; - Fh(tl, 0, "static const struct vrt_backend_probe vgc_probe__%d = {\n", - tl->nprobe++); - while (tl->t->tok != '}') { - - vcc_IsField(tl, &t_field, fs); - ERRCHK(tl); - if (vcc_IdIs(t_field, "url")) { - vcc_ProbeRedef(tl, &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_ProbeRedef(tl, &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, '}'); -} - -/*-------------------------------------------------------------------- - * Parse and emit a probe definition - */ - -void -vcc_ParseProbe(struct vcc *tl) -{ - struct token *t_probe; - int i; - - vcc_NextToken(tl); /* ID: probe */ - - vcc_ExpectCid(tl); /* ID: name */ - ERRCHK(tl); - t_probe = tl->t; - vcc_NextToken(tl); - i = vcc_AddDef(tl, t_probe, SYM_PROBE); - if (i > 1) { - VSB_printf(tl->sb, "Probe %.*s redefined\n", PF(t_probe)); - vcc_ErrWhere(tl, t_probe); - } - - Fh(tl, 0, "\n#define vgc_probe_%.*s\tvgc_probe__%d\n", - PF(t_probe), tl->nprobe); - vcc_ParseProbeSpec(tl); -} - -/*-------------------------------------------------------------------- - * Parse and emit a backend host definition - * - * The struct vrt_backend is emitted to Fh(). - */ - -static void -vcc_ParseHostDef(struct vcc *tl, const struct token *t_be) -{ - struct token *t_field; - struct token *t_host = NULL; - struct token *t_port = NULL; - struct token *t_hosthdr = NULL; - struct fld_spec *fs; - struct vsb *vsb; - unsigned u; - double t; - char vgcname[MAX_BACKEND_NAME + 8]; - - sprintf(vgcname, "_%.*s", PF(t_be)); - - 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", - 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(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, "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, 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); - 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"); - - /* 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,\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++; -} - -/*-------------------------------------------------------------------- - * Parse directors and backends - */ - -void -vcc_ParseBackend(struct vcc *tl) -{ - struct token *t_first, *t_be; - int isfirst; - struct symbol *sym; - - t_first = tl->t; - vcc_NextToken(tl); /* ID: backend */ - - vcc_ExpectCid(tl); /* ID: name */ - ERRCHK(tl); - - if (tl->t->e - tl->t->b > MAX_BACKEND_NAME) { - VSB_printf(tl->sb, - "Name of %.*s too long (max %d, is %zu):\n", - PF(t_first), MAX_BACKEND_NAME, - (size_t)(tl->t->e - tl->t->b)); - vcc_ErrWhere(tl, tl->t); - return; - } - - t_be = tl->t; - vcc_NextToken(tl); - - isfirst = tl->ndirector; - - sym = VCC_GetSymbolTok(tl, t_be, SYM_BACKEND); - AN(sym); - if (sym->ndef > 0) { - VSB_printf(tl->sb, "Backend %.*s redefined\n", PF(t_be)); - vcc_ErrWhere(tl, t_be); - return; - } - sym->fmt = BACKEND; - sym->eval = vcc_Eval_Backend; - sym->ndef++; - ERRCHK(tl); - - vcc_ParseHostDef(tl, t_be); - ERRCHK(tl); - - if (tl->err) { - VSB_printf(tl->sb, - "\nIn %.*s specification starting at:\n", PF(t_first)); - vcc_ErrWhere(tl, t_first); - return; - } - - if (isfirst == 1 || vcc_IdIs(t_be, "default")) { - tl->defaultdir = tl->ndirector - 1; - tl->t_defaultdir = t_be; - } -} diff --git a/lib/libvcl/vcc_backend_util.c b/lib/libvcl/vcc_backend_util.c deleted file mode 100644 index de361a5..0000000 --- a/lib/libvcl/vcc_backend_util.c +++ /dev/null @@ -1,134 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include "config.h" - -#include -#include -#include - -#include "vcc_compile.h" - -/*-------------------------------------------------------------------- - * Helper functions to complain about duplicate and missing fields - * - * XXX: idea: add groups to check for exclusivity, such that - * XXX: ("!foo", "?bar", "!{", "this", "that", "}", NULL) - * XXX: means exactly one of "this" or "that", and - * XXX: ("!foo", "?bar", "?{", "this", "that", "}", NULL) - * XXX: means at most one of "this" or "that". - */ - -struct fld_spec { - const char *name; - struct token *found; -}; - -static void -vcc_ResetFldSpec(struct fld_spec *f) -{ - - for (; f->name != NULL; f++) - f->found = NULL; -} - -struct fld_spec * -vcc_FldSpec(struct vcc *tl, const char *first, ...) -{ - struct fld_spec f[100], *r; - int n = 0; - va_list ap; - const char *p; - - f[n++].name = first; - va_start(ap, first); - while (1) { - p = va_arg(ap, const char *); - if (p == NULL) - break; - f[n++].name = p; - assert(n < 100); - } - va_end(ap); - f[n++].name = NULL; - - vcc_ResetFldSpec(f); - - r = TlAlloc(tl, sizeof *r * n); - memcpy(r, f, n * sizeof *r); - return (r); -} - -void -vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs) -{ - struct token *t_field; - - SkipToken(tl, '.'); - ExpectErr(tl, ID); - t_field = tl->t; - *t = t_field; - vcc_NextToken(tl); - SkipToken(tl, '='); - - for (; fs->name != NULL; fs++) { - if (!vcc_IdIs(t_field, fs->name + 1)) - continue; - if (fs->found == NULL) { - fs->found = t_field; - return; - } - VSB_printf(tl->sb, "Field "); - vcc_ErrToken(tl, t_field); - VSB_printf(tl->sb, " redefined at:\n"); - vcc_ErrWhere(tl, t_field); - VSB_printf(tl->sb, "\nFirst defined at:\n"); - vcc_ErrWhere(tl, fs->found); - return; - } - VSB_printf(tl->sb, "Unknown field: "); - vcc_ErrToken(tl, t_field); - VSB_printf(tl->sb, " at\n"); - vcc_ErrWhere(tl, t_field); - return; -} - -void -vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs) -{ - - for (; fs->name != NULL; fs++) { - if (*fs->name == '!' && fs->found == NULL) { - VSB_printf(tl->sb, - "Mandatory field '%s' missing.\n", fs->name + 1); - tl->err = 1; - } - } -} diff --git a/lib/libvcl/vcc_compile.c b/lib/libvcl/vcc_compile.c deleted file mode 100644 index 07eef41..0000000 --- a/lib/libvcl/vcc_compile.c +++ /dev/null @@ -1,823 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * XXX: - * Better error messages, throughout. - * >It also accured to me that we could link the errors to the error - * >documentation. - * > - * >Unreferenced function 'request_policy', first mention is - * > Line 8 Pos 4 - * > sub request_policy { - * > ----##############-- - * >Read more about this type of error: - * >http://varnish/doc/error.html#Unreferenced%20function - * > - * > - * > Unknown variable 'obj.bandwidth' - * > At: Line 88 Pos 12 - * > if (obj.bandwidth < 1 kb/h) { - * > ------------#############------------ - * >Read more about this type of error: - * >http://varnish/doc/error.html#Unknown%20variable - * - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include "vcc_compile.h" - -#include "libvcl.h" -#include "vfil.h" - -struct method method_tab[] = { -#define VCL_MET_MAC(l,U,m) { "vcl_"#l, m, VCL_MET_##U }, -#include "tbl/vcl_returns.h" -#undef VCL_MET_MAC - { NULL, 0U, 0} -}; - -/*--------------------------------------------------------------------*/ - -static void -TlDoFree(struct vcc *tl, void *p) -{ - struct membit *mb; - - mb = calloc(sizeof *mb, 1); - assert(mb != NULL); - mb->ptr = p; - VTAILQ_INSERT_TAIL(&tl->membits, mb, list); -} - - -void * -TlAlloc(struct vcc *tl, unsigned len) -{ - void *p; - - p = calloc(len, 1); - assert(p != NULL); - TlDoFree(tl, p); - return (p); -} - -char * -TlDup(struct vcc *tl, const char *s) -{ - char *p; - - p = TlAlloc(tl, strlen(s) + 1); - AN(p); - strcpy(p, s); - return (p); -} - -char * -TlDupTok(struct vcc *tl, const struct token *tok) -{ - char *p; - int i; - - i = tok->e - tok->b; - p = TlAlloc(tl, i + 1); - AN(p); - memcpy(p, tok->b, i); - p[i] = '\0'; - return (p); -} - -/*--------------------------------------------------------------------*/ - -int -IsMethod(const struct token *t) -{ - struct method *m; - - assert(t->tok == ID); - for(m = method_tab; m->name != NULL; m++) { - if (vcc_IdIs(t, m->name)) - return (m - method_tab); - } - if ((t->b[0] == 'v'|| t->b[0] == 'V') && - (t->b[1] == 'c'|| t->b[1] == 'C') && - (t->b[2] == 'l'|| t->b[2] == 'L')) - return (-2); - return (-1); -} - -/*-------------------------------------------------------------------- - * Printf output to the vsbs, possibly indented - */ - -void -Fh(const struct vcc *tl, int indent, const char *fmt, ...) -{ - va_list ap; - - if (indent) - VSB_printf(tl->fh, "%*.*s", tl->hindent, tl->hindent, ""); - va_start(ap, fmt); - VSB_vprintf(tl->fh, fmt, ap); - va_end(ap); -} - -void -Fb(const struct vcc *tl, int indent, const char *fmt, ...) -{ - va_list ap; - - assert(tl->fb != NULL); - if (indent) - VSB_printf(tl->fb, "%*.*s", tl->indent, tl->indent, ""); - va_start(ap, fmt); - VSB_vprintf(tl->fb, fmt, ap); - va_end(ap); -} - -void -Fc(const struct vcc *tl, int indent, const char *fmt, ...) -{ - va_list ap; - - if (indent) - VSB_printf(tl->fc, "%*.*s", tl->indent, tl->indent, ""); - va_start(ap, fmt); - VSB_vprintf(tl->fc, fmt, ap); - va_end(ap); -} - -void -Fi(const struct vcc *tl, int indent, const char *fmt, ...) -{ - va_list ap; - - if (indent) - VSB_printf(tl->fi, "%*.*s", tl->iindent, tl->iindent, ""); - va_start(ap, fmt); - VSB_vprintf(tl->fi, fmt, ap); - va_end(ap); -} - -void -Fd(const struct vcc *tl, int indent, const char *fmt, ...) -{ - va_list ap; - - if (indent) - VSB_printf(tl->fd, "%*.*s", tl->findent, tl->findent, ""); - va_start(ap, fmt); - VSB_vprintf(tl->fd, fmt, ap); - va_end(ap); -} - - -void -Ff(const struct vcc *tl, int indent, const char *fmt, ...) -{ - va_list ap; - - if (indent) - VSB_printf(tl->ff, "%*.*s", tl->findent, tl->findent, ""); - va_start(ap, fmt); - VSB_vprintf(tl->ff, fmt, ap); - va_end(ap); -} - -/*--------------------------------------------------------------------*/ - -void -EncString(struct vsb *sb, const char *b, const char *e, int mode) -{ - - if (e == NULL) - e = strchr(b, '\0'); - - VSB_cat(sb, "\""); - for (; b < e; b++) { - switch (*b) { - case '\\': - case '"': - VSB_printf(sb, "\\%c", *b); - break; - case '\n': - VSB_printf(sb, "\\n"); - if (mode) - VSB_printf(sb, "\"\n\t\""); - break; - case '\t': VSB_printf(sb, "\\t"); break; - case '\r': VSB_printf(sb, "\\r"); break; - case ' ': VSB_printf(sb, " "); break; - default: - if (isgraph(*b)) - VSB_printf(sb, "%c", *b); - else - VSB_printf(sb, "\\%03o", (uint8_t)*b); - break; - } - } - VSB_cat(sb, "\""); -} - -void -EncToken(struct vsb *sb, const struct token *t) -{ - - assert(t->tok == CSTR); - EncString(sb, t->dec, NULL, 1); -} - -/*-------------------------------------------------------------------- - * Output the location/profiling table. For each counted token, we - * record source+line+charpos for the first character in the token. - */ - -static void -LocTable(const struct vcc *tl) -{ - struct token *t; - unsigned lin, pos; - struct source *sp; - const char *p; - - Fh(tl, 0, "\n#define VGC_NREFS %u\n", tl->cnt + 1); - Fc(tl, 0, "\nstatic struct vrt_ref VGC_ref[VGC_NREFS] = {\n"); - lin = 1; - pos = 0; - sp = 0; - p = NULL; - VTAILQ_FOREACH(t, &tl->tokens, list) { - if (t->cnt == 0) - continue; - assert(t->src != NULL); - if (t->src != sp) { - lin = 1; - pos = 0; - sp = t->src; - p = sp->b; - } - assert(sp != NULL); - assert(p != NULL); - for (;p < t->b; p++) { - if (*p == '\n') { - lin++; - pos = 0; - } else if (*p == '\t') { - pos &= ~7; - pos += 8; - } else - pos++; - - } - Fc(tl, 0, " [%3u] = { %d, %8tu, %4u, %3u, 0, ", - t->cnt, sp->idx, t->b - sp->b, lin, pos + 1); - if (t->tok == CSRC) - Fc(tl, 0, " \"C{\"},\n"); - else - Fc(tl, 0, " \"%.*s\" },\n", PF(t)); - } - Fc(tl, 0, "};\n"); -} - -/*--------------------------------------------------------------------*/ - -static void -EmitInitFunc(const struct vcc *tl) -{ - - Fc(tl, 0, "\nstatic int\nVGC_Init(struct cli *cli)\n{\n\n"); - AZ(VSB_finish(tl->fi)); - VSB_cat(tl->fc, VSB_data(tl->fi)); - Fc(tl, 0, "\treturn(0);\n"); - Fc(tl, 0, "}\n"); -} - -static void -EmitFiniFunc(const struct vcc *tl) -{ - unsigned u; - - Fc(tl, 0, "\nstatic void\nVGC_Fini(struct cli *cli)\n{\n\n"); - - AZ(VSB_finish(tl->fd)); - VSB_cat(tl->fc, VSB_data(tl->fd)); - - /* - * We do this here, so we are sure they happen before any - * per-vcl vmod_privs get cleaned. - */ - for (u = 0; u < tl->nvmodpriv; u++) - Fc(tl, 0, "\tvmod_priv_fini(&vmod_priv_%u);\n", u); - - AZ(VSB_finish(tl->ff)); - VSB_cat(tl->fc, VSB_data(tl->ff)); - Fc(tl, 0, "}\n"); -} - -/*--------------------------------------------------------------------*/ - -static void -EmitStruct(const struct vcc *tl) -{ - struct source *sp; - - Fc(tl, 0, "\nconst char *srcname[%u] = {\n", tl->nsources); - VTAILQ_FOREACH(sp, &tl->sources, list) { - Fc(tl, 0, "\t"); - EncString(tl->fc, sp->name, NULL, 0); - Fc(tl, 0, ",\n"); - } - Fc(tl, 0, "};\n"); - - Fc(tl, 0, "\nconst char *srcbody[%u] = {\n", tl->nsources); - VTAILQ_FOREACH(sp, &tl->sources, list) { - Fc(tl, 0, " /* "); - EncString(tl->fc, sp->name, NULL, 0); - Fc(tl, 0, "*/\n"); - Fc(tl, 0, "\t"); - EncString(tl->fc, sp->b, sp->e, 1); - Fc(tl, 0, ",\n"); - } - Fc(tl, 0, "};\n"); - - Fc(tl, 0, "\nstatic struct director\t*directors[%d];\n", - tl->ndirector); - - Fc(tl, 0, "\nconst struct VCL_conf VCL_conf = {\n"); - Fc(tl, 0, "\t.magic = VCL_CONF_MAGIC,\n"); - Fc(tl, 0, "\t.init_vcl = VGC_Init,\n"); - Fc(tl, 0, "\t.fini_vcl = VGC_Fini,\n"); - Fc(tl, 0, "\t.ndirector = %d,\n", tl->ndirector); - Fc(tl, 0, "\t.director = directors,\n"); - Fc(tl, 0, "\t.ref = VGC_ref,\n"); - Fc(tl, 0, "\t.nref = VGC_NREFS,\n"); - Fc(tl, 0, "\t.nsrc = %u,\n", tl->nsources); - Fc(tl, 0, "\t.srcname = srcname,\n"); - Fc(tl, 0, "\t.srcbody = srcbody,\n"); -#define VCL_MET_MAC(l,u,b) \ - Fc(tl, 0, "\t." #l "_func = VGC_function_vcl_" #l ",\n"); -#include "tbl/vcl_returns.h" -#undef VCL_MET_MAC - Fc(tl, 0, "};\n"); -} - -/*--------------------------------------------------------------------*/ - -static struct source * -vcc_new_source(const char *b, const char *e, const char *name) -{ - struct source *sp; - - if (e == NULL) - e = strchr(b, '\0'); - sp = calloc(sizeof *sp, 1); - assert(sp != NULL); - sp->name = strdup(name); - AN(sp->name); - sp->b = b; - sp->e = e; - return (sp); -} - -static void -vcc_destroy_source(struct source *sp) -{ - - if (sp->freeit != NULL) - free(sp->freeit); - free(sp->name); - free(sp); -} - -/*--------------------------------------------------------------------*/ - -static struct source * -vcc_file_source(const struct vcc *tl, struct vsb *sb, const char *fn) -{ - char *f; - struct source *sp; - - if (!tl->unsafe_path && strchr(fn, '/') != NULL) { - VSB_printf(sb, "Include path is unsafe '%s'\n", fn); - return (NULL); - } - f = VFIL_readfile(tl->vcl_dir, fn, NULL); - if (f == NULL) { - VSB_printf(sb, "Cannot read file '%s': %s\n", - fn, strerror(errno)); - return (NULL); - } - sp = vcc_new_source(f, NULL, fn); - sp->freeit = f; - return (sp); -} - -/*--------------------------------------------------------------------*/ - -static void -vcc_resolve_includes(struct vcc *tl) -{ - struct token *t, *t1, *t2; - struct source *sp; - - VTAILQ_FOREACH(t, &tl->tokens, list) { - if (t->tok != ID || !vcc_IdIs(t, "include")) - continue; - - t1 = VTAILQ_NEXT(t, list); - assert(t1 != NULL); /* There's always an EOI */ - if (t1->tok != CSTR) { - VSB_printf(tl->sb, - "include not followed by string constant.\n"); - vcc_ErrWhere(tl, t1); - return; - } - t2 = VTAILQ_NEXT(t1, list); - assert(t2 != NULL); /* There's always an EOI */ - - if (t2->tok != ';') { - VSB_printf(tl->sb, - "include not followed by semicolon.\n"); - vcc_ErrWhere(tl, t1); - return; - } - - sp = vcc_file_source(tl, tl->sb, t1->dec); - if (sp == NULL) { - vcc_ErrWhere(tl, t1); - return; - } - VTAILQ_INSERT_TAIL(&tl->sources, sp, list); - sp->idx = tl->nsources++; - tl->t = t2; - vcc_Lexer(tl, sp); - - VTAILQ_REMOVE(&tl->tokens, t, list); - VTAILQ_REMOVE(&tl->tokens, t1, list); - VTAILQ_REMOVE(&tl->tokens, t2, list); - if (!tl->err) - vcc_resolve_includes(tl); - return; - } -} - -/*--------------------------------------------------------------------*/ - -static struct vcc * -vcc_NewVcc(const struct vcc *tl0) -{ - struct vcc *tl; - int i; - - ALLOC_OBJ(tl, VCC_MAGIC); - AN(tl); - if (tl0 != NULL) { - REPLACE(tl->default_vcl, tl0->default_vcl); - REPLACE(tl->vcl_dir, tl0->vcl_dir); - REPLACE(tl->vmod_dir, tl0->vmod_dir); - tl->vars = tl0->vars; - tl->err_unref = tl0->err_unref; - tl->allow_inline_c = tl0->allow_inline_c; - tl->unsafe_path = tl0->unsafe_path; - } else { - tl->err_unref = 1; - } - VTAILQ_INIT(&tl->symbols); - VTAILQ_INIT(&tl->membits); - VTAILQ_INIT(&tl->tokens); - VTAILQ_INIT(&tl->sources); - - tl->nsources = 0; - tl->ndirector = 1; - - /* General C code */ - tl->fc = VSB_new_auto(); - assert(tl->fc != NULL); - - /* Forward decls (.h like) */ - tl->fh = VSB_new_auto(); - assert(tl->fh != NULL); - - /* Init C code */ - tl->fi = VSB_new_auto(); - assert(tl->fi != NULL); - - /* Destroy Objects */ - tl->fd = VSB_new_auto(); - assert(tl->fd != NULL); - - /* Finish C code */ - tl->ff = VSB_new_auto(); - assert(tl->ff != NULL); - - /* body code of methods */ - for (i = 0; i < VCL_MET_MAX; i++) { - tl->fm[i] = VSB_new_auto(); - assert(tl->fm[i] != NULL); - } - return (tl); -} - -/*--------------------------------------------------------------------*/ - -static char * -vcc_DestroyTokenList(struct vcc *tl, char *ret) -{ - struct membit *mb; - struct source *sp; - struct symbol *sym; - int i; - - while (!VTAILQ_EMPTY(&tl->membits)) { - mb = VTAILQ_FIRST(&tl->membits); - VTAILQ_REMOVE(&tl->membits, mb, list); - free(mb->ptr); - free(mb); - } - while (!VTAILQ_EMPTY(&tl->sources)) { - sp = VTAILQ_FIRST(&tl->sources); - VTAILQ_REMOVE(&tl->sources, sp, list); - vcc_destroy_source(sp); - } - - while (!VTAILQ_EMPTY(&tl->symbols)) { - sym = VTAILQ_FIRST(&tl->symbols); - VTAILQ_REMOVE(&tl->symbols, sym, list); - FREE_OBJ(sym); - } - - VSB_delete(tl->fh); - VSB_delete(tl->fc); - VSB_delete(tl->fi); - VSB_delete(tl->ff); - for (i = 0; i < VCL_MET_MAX; i++) - VSB_delete(tl->fm[i]); - - free(tl); - return (ret); -} - -/*-------------------------------------------------------------------- - * Compile the VCL code from the given source and return the C-source - */ - -static char * -vcc_CompileSource(const struct vcc *tl0, struct vsb *sb, struct source *sp) -{ - struct vcc *tl; - struct symbol *sym; - const struct var *v; - char *of; - int i; - - tl = vcc_NewVcc(tl0); - tl->sb = sb; - - vcc_Expr_Init(tl); - - for (v = tl->vars; v->name != NULL; v++) { - if (v->fmt == HEADER) { - sym = VCC_AddSymbolStr(tl, v->name, SYM_WILDCARD); - sym->wildcard = vcc_Var_Wildcard; - } else { - sym = VCC_AddSymbolStr(tl, v->name, SYM_VAR); - } - sym->var = v; - sym->fmt = v->fmt; - sym->eval = vcc_Eval_Var; - sym->r_methods = v->r_methods; - } - - sym = VCC_AddSymbolStr(tl, "storage.", SYM_WILDCARD); - sym->wildcard = vcc_Stv_Wildcard; - - vcl_output_lang_h(tl->fh); - Fh(tl, 0, "\n/* ---===### VCC generated below here ###===---*/\n"); - Fh(tl, 0, "\nextern const struct VCL_conf VCL_conf;\n"); - - /* Macro for accessing directors */ - Fh(tl, 0, "#define VGCDIR(n) VCL_conf.director[VGC_backend_##n]\n"); - - Fh(tl, 0, "#define __match_proto__(xxx) /*lint -e{818} */\n"); - - /* Register and lex the main source */ - VTAILQ_INSERT_TAIL(&tl->sources, sp, list); - sp->idx = tl->nsources++; - vcc_Lexer(tl, sp); - if (tl->err) - return (vcc_DestroyTokenList(tl, NULL)); - - /* Register and lex the default VCL */ - sp = vcc_new_source(tl->default_vcl, NULL, "Default"); - assert(sp != NULL); - VTAILQ_INSERT_TAIL(&tl->sources, sp, list); - sp->idx = tl->nsources++; - vcc_Lexer(tl, sp); - if (tl->err) - return (vcc_DestroyTokenList(tl, NULL)); - - /* Add "END OF INPUT" token */ - vcc_AddToken(tl, EOI, sp->e, sp->e); - if (tl->err) - return (vcc_DestroyTokenList(tl, NULL)); - - /* Expand and lex any includes in the token string */ - vcc_resolve_includes(tl); - if (tl->err) - return (vcc_DestroyTokenList(tl, NULL)); - - /* Parse the token string */ - tl->t = VTAILQ_FIRST(&tl->tokens); - vcc_Parse(tl); - if (tl->err) - return (vcc_DestroyTokenList(tl, NULL)); - - /* Check if we have any backends at all */ - if (tl->ndirector == 1) { - VSB_printf(tl->sb, - "No backends or directors found in VCL program, " - "at least one is necessary.\n"); - tl->err = 1; - return (vcc_DestroyTokenList(tl, NULL)); - } - - /* Configure the default director */ - Fi(tl, 0, "\tVCL_conf.director[0] = VCL_conf.director[%d];\n", - tl->defaultdir); - vcc_AddRef(tl, tl->t_defaultdir, SYM_BACKEND); - - /* Check for orphans */ - if (vcc_CheckReferences(tl)) - return (vcc_DestroyTokenList(tl, NULL)); - - /* Check that all action returns are legal */ - if (vcc_CheckAction(tl) || tl->err) - return (vcc_DestroyTokenList(tl, NULL)); - - /* Check that all variable uses are legal */ - if (vcc_CheckUses(tl) || tl->err) - return (vcc_DestroyTokenList(tl, NULL)); - - /* Emit method functions */ - for (i = 0; i < VCL_MET_MAX; i++) { - Fc(tl, 1, "\nstatic int __match_proto__(vcl_func_f)\n"); - Fc(tl, 1, - "VGC_function_%s(const struct vrt_ctx *ctx)\n", - method_tab[i].name); - AZ(VSB_finish(tl->fm[i])); - Fc(tl, 1, "{\n"); - Fc(tl, 1, "%s", VSB_data(tl->fm[i])); - Fc(tl, 1, "}\n"); - } - - LocTable(tl); - - EmitInitFunc(tl); - - EmitFiniFunc(tl); - - EmitStruct(tl); - - /* Combine it all in the fh vsb */ - AZ(VSB_finish(tl->fc)); - VSB_cat(tl->fh, VSB_data(tl->fc)); - AZ(VSB_finish(tl->fh)); - - of = strdup(VSB_data(tl->fh)); - AN(of); - - /* done */ - return (vcc_DestroyTokenList(tl, of)); -} - -/*-------------------------------------------------------------------- - * Compile the VCL code in the argument. Error messages, if any are - * formatted into the vsb. - */ - -char * -VCC_Compile(const struct vcc *tl, struct vsb *sb, const char *b) -{ - struct source *sp; - char *r; - - sp = vcc_new_source(b, NULL, "input"); - if (sp == NULL) - return (NULL); - r = vcc_CompileSource(tl, sb, sp); - return (r); -} - -/*-------------------------------------------------------------------- - * Allocate a compiler instance - */ - -struct vcc * -VCC_New(void) -{ - struct vcc *tl; - - tl = vcc_NewVcc(NULL); - - tl->vars = vcc_vars; - - return (tl); -} - -/*-------------------------------------------------------------------- - * Configure default VCL source code - */ - -void -VCC_Default_VCL(struct vcc *tl, const char *str) -{ - - CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); - REPLACE(tl->default_vcl, str); -} - -/*-------------------------------------------------------------------- - * Configure default VCL source directory - */ - -void -VCC_VCL_dir(struct vcc *tl, const char *str) -{ - - CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); - REPLACE(tl->vcl_dir, str); -} - -/*-------------------------------------------------------------------- - * Configure default VMOD directory - */ - -void -VCC_VMOD_dir(struct vcc *tl, const char *str) -{ - - CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); - REPLACE(tl->vmod_dir, str); -} - -/*-------------------------------------------------------------------- - * Configure settings - */ - -void -VCC_Err_Unref(struct vcc *tl, unsigned u) -{ - - CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); - tl->err_unref = u; -} - -void -VCC_Allow_InlineC(struct vcc *tl, unsigned u) -{ - - CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); - tl->allow_inline_c = u; -} - -void -VCC_Unsafe_Path(struct vcc *tl, unsigned u) -{ - - CHECK_OBJ_NOTNULL(tl, VCC_MAGIC); - tl->unsafe_path = u; -} diff --git a/lib/libvcl/vcc_compile.h b/lib/libvcl/vcc_compile.h deleted file mode 100644 index b0983cc..0000000 --- a/lib/libvcl/vcc_compile.h +++ /dev/null @@ -1,351 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include - -#include -#include -#include - -#include "miniobj.h" -#include "vas.h" -#include "vcl.h" -#include "vdef.h" -#include "vqueue.h" -#include "vsb.h" - - -#include "vcc_token_defs.h" - -#ifndef NULL -#define NULL ((void*)0) -#endif - -struct vsb; -struct token; -struct sockaddr_storage; - -#define isident1(c) (isalpha(c)) -#define isident(c) (isalpha(c) || isdigit(c) || (c) == '_' || (c) == '-') -#define isvar(c) (isident(c) || (c) == '.') -int vcc_isCid(const struct token *t); -unsigned vcl_fixed_token(const char *p, const char **q); -extern const char * const vcl_tnames[256]; -void vcl_output_lang_h(struct vsb *sb); - -#define PF(t) (int)((t)->e - (t)->b), (t)->b - -#define INDENT 2 - -struct acl_e; -struct proc; -struct expr; -struct vcc; -struct symbol; - -enum var_type { -#define VCC_TYPE(foo) foo, -#include "tbl/vcc_types.h" -#undef VCC_TYPE -}; - -struct membit { - VTAILQ_ENTRY(membit) list; - void *ptr; -}; - -struct source { - VTAILQ_ENTRY(source) list; - char *name; - const char *b; - const char *e; - unsigned idx; - char *freeit; -}; - -struct token { - unsigned tok; - const char *b; - const char *e; - struct source *src; - VTAILQ_ENTRY(token) list; - unsigned cnt; - char *dec; -}; - -enum symkind { -#define VCC_SYMB(uu, ll) SYM_##uu, -#include "tbl/symbol_kind.h" -#undef VCC_SYMB -}; - -typedef void sym_expr_t(struct vcc *tl, struct expr **, - const struct symbol *sym); -typedef struct symbol *sym_wildcard_t(struct vcc *tl, const struct token *t, - const struct symbol *sym); - -struct symbol { - unsigned magic; -#define SYMBOL_MAGIC 0x3368c9fb - VTAILQ_ENTRY(symbol) list; - - char *name; - unsigned nlen; - sym_wildcard_t *wildcard; - enum symkind kind; - - const struct token *def_b, *def_e; - - enum var_type fmt; - - sym_expr_t *eval; - void *eval_priv; - - /* xref.c */ - struct proc *proc; - unsigned nref, ndef; - - /* SYM_PROC, SYM_FUNC */ - const char *cfunc; - const char *extra; - const char *args; - - /* SYM_VAR */ - const struct var *var; - unsigned r_methods; -}; - -VTAILQ_HEAD(tokenhead, token); - -struct vcc { - unsigned magic; -#define VCC_MAGIC 0x24ad719d - - /* Parameter/Template section */ - char *default_vcl; - char *vcl_dir; - char *vmod_dir; - - const struct var *vars; - VTAILQ_HEAD(, symbol) symbols; - - /* Instance section */ - struct tokenhead tokens; - VTAILQ_HEAD(, source) sources; - VTAILQ_HEAD(, membit) membits; - unsigned nsources; - struct source *src; - struct token *t; - int indent; - int hindent; - int iindent; - int findent; - unsigned cnt; - - struct vsb *fc; /* C-code */ - struct vsb *fh; /* H-code (before C-code) */ - struct vsb *fi; /* Init func code */ - struct vsb *fd; /* Object destructors */ - struct vsb *ff; /* Finish func code */ - struct vsb *fb; /* Body of current sub - * NULL otherwise - */ - struct vsb *fm[VCL_MET_MAX]; /* Method bodies */ - struct vsb *sb; - int err; - int ndirector; - struct proc *curproc; - struct proc *mprocs[VCL_MET_MAX]; - - VTAILQ_HEAD(, acl_e) acl; - - int nprobe; - - int defaultdir; - struct token *t_defaultdir; - - unsigned unique; - unsigned nvmodpriv; - - unsigned err_unref; - unsigned allow_inline_c; - unsigned unsafe_path; -}; - -struct var { - const char *name; - enum var_type fmt; - unsigned len; - const char *rname; - unsigned r_methods; - const char *lname; - unsigned w_methods; -}; - -struct method { - const char *name; - unsigned ret_bitmap; - unsigned bitval; -}; - -/*--------------------------------------------------------------------*/ - -/* vcc_acl.c */ - -void vcc_Acl(struct vcc *tl); -void vcc_Acl_Hack(struct vcc *tl, char *b); - -/* vcc_action.c */ -int vcc_ParseAction(struct vcc *tl); - -/* vcc_backend.c */ -#define MAX_BACKEND_NAME 64 -struct fld_spec; - -void vcc_ParseProbe(struct vcc *tl); -void vcc_ParseBackend(struct vcc *tl); -struct fld_spec * vcc_FldSpec(struct vcc *tl, const char *first, ...); -void vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs); -void vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs); - -/* vcc_compile.c */ -extern struct method method_tab[]; -/* - * H -> Header, before the C code - * C -> C-code - * B -> Body of function, ends up in C once function is completed - * I -> Initializer function - * F -> Finish function - */ -void Fh(const struct vcc *tl, int indent, const char *fmt, ...) - __printflike(3, 4); -void Fc(const struct vcc *tl, int indent, const char *fmt, ...) - __printflike(3, 4); -void Fb(const struct vcc *tl, int indent, const char *fmt, ...) - __printflike(3, 4); -void Fi(const struct vcc *tl, int indent, const char *fmt, ...) - __printflike(3, 4); -void Ff(const struct vcc *tl, int indent, const char *fmt, ...) - __printflike(3, 4); -void Fd(const struct vcc *tl, int indent, const char *fmt, ...) - __printflike(3, 4); -void EncToken(struct vsb *sb, const struct token *t); -int IsMethod(const struct token *t); -void *TlAlloc(struct vcc *tl, unsigned len); -char *TlDup(struct vcc *tl, const char *s); -char *TlDupTok(struct vcc *tl, const struct token *tok); - -void EncString(struct vsb *sb, const char *b, const char *e, int mode); - -/* vcc_expr.c */ -void vcc_Duration(struct vcc *tl, double *); -unsigned vcc_UintVal(struct vcc *tl); -void vcc_Expr(struct vcc *tl, enum var_type typ); -void vcc_Expr_Call(struct vcc *tl, const struct symbol *sym); -void vcc_Expr_Init(struct vcc *tl); -sym_expr_t vcc_Eval_Var; -sym_expr_t vcc_Eval_SymFunc; -void vcc_Eval_Func(struct vcc *tl, const char *cfunc, const char *extra, - const char *name, const char *args); -sym_expr_t vcc_Eval_Backend; - -/* vcc_obj.c */ -extern const struct var vcc_vars[]; - -/* vcc_parse.c */ -void vcc_Parse(struct vcc *tl); - -/* vcc_storage.c */ -sym_wildcard_t vcc_Stv_Wildcard; - -/* vcc_utils.c */ -const char *vcc_regexp(struct vcc *tl); -void Resolve_Sockaddr(struct vcc *tl, const char *host, const char *port, \ - const char **ipv4, const char **ipv4_ascii, const char **ipv6, \ - const char **ipv6_ascii, const char **p_ascii, int maxips, - const struct token *t_err, const char *errid); - -/* vcc_symb.c */ -struct symbol *VCC_AddSymbolStr(struct vcc *tl, const char *name, enum symkind); -struct symbol *VCC_AddSymbolTok(struct vcc *tl, const struct token *t, - enum symkind kind); -struct symbol *VCC_GetSymbolTok(struct vcc *tl, const struct token *tok, - enum symkind); -struct symbol *VCC_FindSymbol(struct vcc *tl, - const struct token *t, enum symkind kind); -const char * VCC_SymKind(struct vcc *tl, const struct symbol *s); -typedef void symwalk_f(struct vcc *tl, const struct symbol *s); -void VCC_WalkSymbols(struct vcc *tl, symwalk_f *func, enum symkind kind); - -/* vcc_token.c */ -void vcc_Coord(const struct vcc *tl, struct vsb *vsb, - const struct token *t); -void vcc_ErrToken(const struct vcc *tl, const struct token *t); -void vcc_ErrWhere(struct vcc *, const struct token *); -void vcc_ErrWhere2(struct vcc *, const struct token *, const struct token *); - -void vcc__Expect(struct vcc *tl, unsigned tok, unsigned line); -int vcc_IdIs(const struct token *t, const char *p); -void vcc_ExpectCid(struct vcc *tl); -void vcc_Lexer(struct vcc *tl, struct source *sp); -void vcc_NextToken(struct vcc *tl); -void vcc__ErrInternal(struct vcc *tl, const char *func, - unsigned line); -void vcc_AddToken(struct vcc *tl, unsigned tok, const char *b, - const char *e); - -/* vcc_var.c */ -sym_wildcard_t vcc_Var_Wildcard; -const struct var *vcc_FindVar(struct vcc *tl, const struct token *t, - int wr_access, const char *use); - -/* vcc_vmod.c */ -void vcc_ParseImport(struct vcc *tl); - -/* vcc_xref.c */ -int vcc_AddDef(struct vcc *tl, const struct token *t, enum symkind type); -void vcc_AddRef(struct vcc *tl, const struct token *t, enum symkind type); -int vcc_CheckReferences(struct vcc *tl); - -void vcc_AddCall(struct vcc *tl, struct token *t); -struct proc *vcc_AddProc(struct vcc *tl, struct token *t); -void vcc_ProcAction(struct proc *p, unsigned action, struct token *t); -int vcc_CheckAction(struct vcc *tl); -void vcc_AddUses(struct vcc *tl, const struct token *t, unsigned mask, - const char *use); -int vcc_CheckUses(struct vcc *tl); - -#define ERRCHK(tl) do { if ((tl)->err) return; } while (0) -#define ErrInternal(tl) vcc__ErrInternal(tl, __func__, __LINE__) -#define Expect(a, b) vcc__Expect(a, b, __LINE__) -#define ExpectErr(a, b) \ - do { vcc__Expect(a, b, __LINE__); ERRCHK(a);} while (0) -#define SkipToken(a, b) \ - do { vcc__Expect(a, b, __LINE__); ERRCHK(a); vcc_NextToken(a); } while (0) diff --git a/lib/libvcl/vcc_expr.c b/lib/libvcl/vcc_expr.c deleted file mode 100644 index 164a8d6..0000000 --- a/lib/libvcl/vcc_expr.c +++ /dev/null @@ -1,1257 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * XXX: add VRT_count()'s - */ - -#include "config.h" - -#include -#include -#include -#include -#include - -#include "vcc_compile.h" - -static const char * -vcc_Type(enum var_type fmt) -{ - switch(fmt) { -#define VCC_TYPE(a) case a: return(#a); -#include "tbl/vcc_types.h" -#undef VCC_TYPE - default: - assert("Unknown Type"); - return(NULL); - } -} - -/*-------------------------------------------------------------------- - * Recognize and convert units of time, return seconds. - */ - -static double -vcc_TimeUnit(struct vcc *tl) -{ - double sc = 1.0; - - assert(tl->t->tok == ID); - if (vcc_IdIs(tl->t, "ms")) - sc = 1e-3; - else if (vcc_IdIs(tl->t, "s")) - sc = 1.0; - else if (vcc_IdIs(tl->t, "m")) - sc = 60.0; - else if (vcc_IdIs(tl->t, "h")) - sc = 60.0 * 60.0; - else if (vcc_IdIs(tl->t, "d")) - sc = 60.0 * 60.0 * 24.0; - else if (vcc_IdIs(tl->t, "w")) - sc = 60.0 * 60.0 * 24.0 * 7.0; - else { - VSB_printf(tl->sb, "Unknown time unit "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, ". Legal are 's', 'm', 'h' and 'd'\n"); - vcc_ErrWhere(tl, tl->t); - return (1.0); - } - vcc_NextToken(tl); - return (sc); -} - -/*-------------------------------------------------------------------- - * Recognize and convert { CNUM } to unsigned value - * The tokenizer made sure we only get digits. - */ - -unsigned -vcc_UintVal(struct vcc *tl) -{ - unsigned d = 0; - const char *p; - - Expect(tl, CNUM); - for (p = tl->t->b; p < tl->t->e; p++) { - d *= 10; - d += *p - '0'; - } - vcc_NextToken(tl); - return (d); -} - -/*-------------------------------------------------------------------- - * Recognize and convert { CNUM [ '.' [ CNUM ] ] } to double value - * The tokenizer made sure we only get digits and a '.' - */ - -static void -vcc_NumVal(struct vcc *tl, double *d, int *frac) -{ - double e = 0.1; - const char *p; - - *frac = 0; - *d = 0.0; - Expect(tl, CNUM); - if (tl->err) { - *d = NAN; - return; - } - for (p = tl->t->b; p < tl->t->e; p++) { - *d *= 10; - *d += *p - '0'; - } - vcc_NextToken(tl); - if (tl->t->tok != '.') - return; - *frac = 1; - vcc_NextToken(tl); - if (tl->t->tok != CNUM) - return; - for (p = tl->t->b; p < tl->t->e; p++) { - *d += (*p - '0') * e; - e *= 0.1; - } - vcc_NextToken(tl); -} - -static double -vcc_DoubleVal(struct vcc *tl) -{ - double d; - int i; - - vcc_NumVal(tl, &d, &i); - return (d); -} - -/*--------------------------------------------------------------------*/ - -void -vcc_Duration(struct vcc *tl, double *d) -{ - double v, sc; - - v = vcc_DoubleVal(tl); - ERRCHK(tl); - ExpectErr(tl, ID); - sc = vcc_TimeUnit(tl); - *d = v * sc; -} - -/*--------------------------------------------------------------------*/ - -static void -vcc_ByteVal(struct vcc *tl, double *d) -{ - double v, sc; - - v = vcc_DoubleVal(tl); - ERRCHK(tl); - if (tl->t->tok != ID) { - VSB_printf(tl->sb, "Expected BYTES unit (B, KB, MB...) got "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, "\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - if (vcc_IdIs(tl->t, "B")) - sc = 1.; - else if (vcc_IdIs(tl->t, "KB")) - sc = 1024.; - else if (vcc_IdIs(tl->t, "MB")) - sc = 1024. * 1024.; - else if (vcc_IdIs(tl->t, "GB")) - sc = 1024. * 1024. * 1024.; - else if (vcc_IdIs(tl->t, "TB")) - sc = 1024. * 1024. * 1024. * 1024.; - else { - VSB_printf(tl->sb, "Unknown BYTES unit "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, - ". Legal are 'B', 'KB', 'MB', 'GB' and 'TB'\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - vcc_NextToken(tl); - *d = v * sc; -} - -/*-------------------------------------------------------------------- - * Facility for carrying expressions around and do text-processing on - * them. - */ - -struct expr { - unsigned magic; -#define EXPR_MAGIC 0x38c794ab - enum var_type fmt; - struct vsb *vsb; - uint8_t constant; -#define EXPR_VAR (1<<0) -#define EXPR_CONST (1<<1) -#define EXPR_STR_CONST (1<<2) - struct token *t1, *t2; -}; - -static inline int -vcc_isconst(const struct expr *e) -{ - AN(e->constant); - return (e->constant & EXPR_CONST); -} - -static void vcc_expr0(struct vcc *tl, struct expr **e, enum var_type fmt); - -static struct expr * -vcc_new_expr(void) -{ - struct expr *e; - - /* XXX: use TlAlloc() ? */ - ALLOC_OBJ(e, EXPR_MAGIC); - AN(e); - e->vsb = VSB_new_auto(); - e->fmt = VOID; - e->constant = EXPR_VAR; - return (e); -} - -static struct expr * -vcc_mk_expr(enum var_type fmt, const char *str, ...) - __printflike(2, 3); - -static struct expr * -vcc_mk_expr(enum var_type fmt, const char *str, ...) -{ - va_list ap; - struct expr *e; - - e = vcc_new_expr(); - e->fmt = fmt; - va_start(ap, str); - VSB_vprintf(e->vsb, str, ap); - va_end(ap); - AZ(VSB_finish(e->vsb)); - return (e); -} - -static void -vcc_delete_expr(struct expr *e) -{ - if (e == NULL) - return; - CHECK_OBJ_NOTNULL(e, EXPR_MAGIC); - VSB_delete(e->vsb); - FREE_OBJ(e); -} -/*-------------------------------------------------------------------- - * We want to get the indentation right in the emitted C code so we have - * to represent it symbolically until we are ready to render. - * - * Many of the operations have very schematic output syntaxes, so we - * use the same facility to simplify the text-processing of emitting - * a given operation on two subexpressions. - * - * We use '\v' as the magic escape character. - * \v1 insert subexpression 1 - * \v2 insert subexpression 2 - * \v+ increase indentation - * \v- increase indentation - * anything else is literal - * - * When editing, we check if any of the subexpressions contain a newline - * and issue it as an indented block of so. - * - * XXX: check line lengths in edit, should pass indent in for this - */ - -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); -} - -/*-------------------------------------------------------------------- - * Expand finished expression into C-source code - */ - -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: - WRONG("Illegal format in VCC expression"); - } - p++; - } -} - -/*-------------------------------------------------------------------- - */ - -static enum var_type -vcc_arg_type(const char **p) -{ - -#define VCC_TYPE(a) if (!strcmp(#a, *p)) { *p += strlen(#a) + 1; return (a);} -#include "tbl/vcc_types.h" -#undef VCC_TYPE - return (VOID); -} - -/*-------------------------------------------------------------------- - */ - -static void -vcc_expr_tostring(struct expr **e, enum var_type fmt) -{ - const char *p; - uint8_t constant = EXPR_VAR; - - CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC); - AN(fmt == STRING || fmt == STRING_LIST); - - p = NULL; - switch((*e)->fmt) { - case BACKEND: p = "VRT_BACKEND_string(\v1)"; break; - case BOOL: p = "VRT_BOOL_string(\v1)"; break; - case DURATION: p = "VRT_REAL_string(ctx, \v1)"; break; - /* XXX: should DURATION insist on "s" suffix ? */ - case INT: - if (vcc_isconst(*e)) { - p = "\"\v1\""; - constant = EXPR_CONST; - } else { - p = "VRT_INT_string(ctx, \v1)"; - } - break; - case IP: p = "VRT_IP_string(ctx, \v1)"; break; - case BYTES: p = "VRT_REAL_string(ctx, \v1)"; break; /* XXX */ - case REAL: p = "VRT_REAL_string(ctx, \v1)"; break; - case TIME: p = "VRT_TIME_string(ctx, \v1)"; break; - case HEADER: p = "VRT_GetHdr(ctx, \v1)"; break; - case ENUM: - case STRING: - case STRING_LIST: - break; - default: - INCOMPL(); - break; - } - if (p != NULL) { - *e = vcc_expr_edit(fmt, p, *e, NULL); - (*e)->constant = constant; - } -} - -/*-------------------------------------------------------------------- - */ - -static void -vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym) -{ - struct expr *e2; - int all = sym->eval_priv == NULL ? 0 : 1; - const char *p; - char buf[128]; - - vcc_delete_expr(*e); - SkipToken(tl, ID); - SkipToken(tl, '('); - - vcc_expr0(tl, &e2, STRING); - if (e2 == NULL) - return; - if (e2->fmt != STRING) - vcc_expr_tostring(&e2, STRING); - - SkipToken(tl, ','); - ExpectErr(tl, CSTR); - p = vcc_regexp(tl); - vcc_NextToken(tl); - - bprintf(buf, "VRT_regsub(ctx, %d,\v+\n\v1,\n%s", all, p); - *e = vcc_expr_edit(STRING, buf, e2, *e); - - SkipToken(tl, ','); - vcc_expr0(tl, &e2, STRING); - if (e2 == NULL) - return; - if (e2->fmt != STRING) - vcc_expr_tostring(&e2, STRING); - *e = vcc_expr_edit(STRING, "\v1,\n\v2)\v-", *e, e2); - SkipToken(tl, ')'); -} - -/*-------------------------------------------------------------------- - */ - -static void -vcc_Eval_BoolConst(struct vcc *tl, struct expr **e, const struct symbol *sym) -{ - - vcc_NextToken(tl); - *e = vcc_mk_expr(BOOL, "(0==%d)", sym->eval_priv == NULL ? 1 : 0); - (*e)->constant = EXPR_CONST; -} - -/*-------------------------------------------------------------------- - */ - -void -vcc_Eval_Backend(struct vcc *tl, struct expr **e, const struct symbol *sym) -{ - - assert(sym->kind == SYM_BACKEND); - - vcc_ExpectCid(tl); - vcc_AddRef(tl, tl->t, SYM_BACKEND); - *e = vcc_mk_expr(BACKEND, "VGCDIR(_%.*s)", PF(tl->t)); - (*e)->constant = EXPR_VAR; /* XXX ? */ - vcc_NextToken(tl); -} - -/*-------------------------------------------------------------------- - */ -void -vcc_Eval_Var(struct vcc *tl, struct expr **e, const struct symbol *sym) -{ - const struct var *vp; - - assert(sym->kind == SYM_VAR); - vcc_AddUses(tl, tl->t, sym->r_methods, "Not available"); - vp = vcc_FindVar(tl, tl->t, 0, "cannot be read"); - ERRCHK(tl); - assert(vp != NULL); - *e = vcc_mk_expr(vp->fmt, "%s", vp->rname); - vcc_NextToken(tl); -} - -/*-------------------------------------------------------------------- - */ - -static void -vcc_func(struct vcc *tl, struct expr **e, const char *cfunc, - const char *extra, const char *name, const char *args) -{ - const char *p, *r; - struct expr *e1, *e2; - enum var_type fmt; - char buf[32]; - - AN(cfunc); - AN(args); - AN(name); - SkipToken(tl, '('); - p = args; - if (extra == NULL) - extra = ""; - e2 = vcc_mk_expr(vcc_arg_type(&p), "%s(ctx%s\v+", cfunc, extra); - while (*p != '\0') { - e1 = NULL; - fmt = vcc_arg_type(&p); - if (fmt == VOID && !strcmp(p, "PRIV_VCL")) { - r = strchr(name, '.'); - AN(r); - e1 = vcc_mk_expr(VOID, "&vmod_priv_%.*s", - (int) (r - name), name); - p += strlen(p) + 1; - } else if (fmt == VOID && !strcmp(p, "PRIV_CALL")) { - bprintf(buf, "vmod_priv_%u", tl->nvmodpriv++); - Fh(tl, 0, "struct vmod_priv %s;\n", buf); - e1 = vcc_mk_expr(VOID, "&%s", buf); - p += strlen(p) + 1; - } else if (fmt == ENUM) { - ExpectErr(tl, ID); - ERRCHK(tl); - r = p; - do { - if (vcc_IdIs(tl->t, p)) - break; - p += strlen(p) + 1; - } while (*p != '\0'); - if (*p == '\0') { - VSB_printf(tl->sb, "Wrong enum value."); - VSB_printf(tl->sb, " Expected one of:\n"); - do { - VSB_printf(tl->sb, "\t%s\n", r); - r += strlen(r) + 1; - } while (*r != '\0'); - vcc_ErrWhere(tl, tl->t); - return; - } - e1 = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t)); - while (*p != '\0') - p += strlen(p) + 1; - p++; - SkipToken(tl, ID); - if (*p != '\0') /*lint !e448 */ - SkipToken(tl, ','); - } else { - vcc_expr0(tl, &e1, fmt); - ERRCHK(tl); - if (e1->fmt != fmt) { - VSB_printf(tl->sb, "Wrong argument type."); - VSB_printf(tl->sb, " Expected %s.", - vcc_Type(fmt)); - VSB_printf(tl->sb, " Got %s.\n", - vcc_Type(e1->fmt)); - vcc_ErrWhere2(tl, e1->t1, tl->t); - return; - } - assert(e1->fmt == fmt); - if (e1->fmt == STRING_LIST) { - e1 = vcc_expr_edit(STRING_LIST, - "\v+\n\v1,\nvrt_magic_string_end\v-", - e1, NULL); - } - if (*p != '\0') - SkipToken(tl, ','); - } - e2 = vcc_expr_edit(e2->fmt, "\v1,\n\v2", e2, e1); - } - SkipToken(tl, ')'); - e2 = vcc_expr_edit(e2->fmt, "\v1\n)\v-", e2, NULL); - *e = e2; -} - -/*-------------------------------------------------------------------- - */ - -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_Eval_SymFunc(struct vcc *tl, struct expr **e, const struct symbol *sym) -{ - - assert(sym->kind == SYM_FUNC || sym->kind == SYM_PROC); - AN(sym->cfunc); - AN(sym->name); - AN(sym->args); - SkipToken(tl, ID); - vcc_func(tl, e, sym->cfunc, sym->extra, sym->name, sym->args); -} - -/*-------------------------------------------------------------------- - * SYNTAX: - * Expr4: - * '(' Expr0 ')' - * CNUM - * CSTR - */ - -static void -vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt) -{ - struct expr *e1, *e2; - const char *ip; - const struct symbol *sym; - double d; - - *e = NULL; - if (tl->t->tok == '(') { - SkipToken(tl, '('); - vcc_expr0(tl, &e2, fmt); - ERRCHK(tl); - SkipToken(tl, ')'); - *e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL); - return; - } - switch(tl->t->tok) { - case ID: - /* - * XXX: what if var and func/proc had same name ? - * XXX: look for SYM_VAR first for consistency ? - */ - sym = VCC_FindSymbol(tl, tl->t, SYM_NONE); - if (sym == NULL || sym->eval == NULL) { - VSB_printf(tl->sb, "Symbol not found: "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, " (expected type %s):\n", - vcc_Type(fmt)); - vcc_ErrWhere(tl, tl->t); - return; - } - AN(sym); - switch(sym->kind) { - case SYM_VAR: - case SYM_FUNC: - case SYM_BACKEND: - AN(sym->eval); - AZ(*e); - sym->eval(tl, e, sym); - return; - default: - break; - } - VSB_printf(tl->sb, - "Symbol type (%s) can not be used in expression.\n", - VCC_SymKind(tl, sym)); - vcc_ErrWhere(tl, tl->t); - return; - case CSTR: - assert(fmt != VOID); - if (fmt == IP) { - Resolve_Sockaddr(tl, tl->t->dec, "80", - &ip, NULL, &ip, NULL, NULL, 1, - tl->t, "IP constant"); - ERRCHK(tl); - e1 = vcc_mk_expr(IP, "%s", ip); - ERRCHK(tl); - } else { - e1 = vcc_new_expr(); - EncToken(e1->vsb, tl->t); - e1->fmt = STRING; - AZ(VSB_finish(e1->vsb)); - } - e1->t1 = tl->t; - e1->constant = EXPR_CONST; - vcc_NextToken(tl); - *e = e1; - break; - case CNUM: - /* - * XXX: %g may not have enough decimals by default - * XXX: but %a is ugly, isn't it ? - */ - assert(fmt != VOID); - if (fmt == DURATION) { - vcc_Duration(tl, &d); - ERRCHK(tl); - e1 = vcc_mk_expr(DURATION, "%g", d); - } else if (fmt == BYTES) { - vcc_ByteVal(tl, &d); - ERRCHK(tl); - e1 = vcc_mk_expr(BYTES, "%.1f", d); - ERRCHK(tl); - } else if (fmt == REAL) { - e1 = vcc_mk_expr(REAL, "%g", vcc_DoubleVal(tl)); - ERRCHK(tl); - } else { - e1 = vcc_mk_expr(INT, "%.*s", PF(tl->t)); - vcc_NextToken(tl); - } - e1->constant = EXPR_CONST; - *e = e1; - break; - default: - VSB_printf(tl->sb, "Unknown token "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, " when looking for %s\n\n", vcc_Type(fmt)); - vcc_ErrWhere(tl, tl->t); - break; - } -} - -/*-------------------------------------------------------------------- - * SYNTAX: - * Expr3: - * Expr4 { {'*'|'/'} Expr4 } * - */ - -static void -vcc_expr_mul(struct vcc *tl, struct expr **e, enum var_type fmt) -{ - struct expr *e2; - enum var_type f2, f3; - struct token *tk; - - *e = NULL; - vcc_expr4(tl, e, fmt); - ERRCHK(tl); - f3 = f2 = (*e)->fmt; - - switch(f2) { - case INT: f2 = INT; break; - case DURATION: f2 = REAL; break; - case BYTES: f2 = REAL; break; - default: - if (tl->t->tok != '*' && tl->t->tok != '/') - return; - VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n", - PF(tl->t), vcc_Type(f2)); - vcc_ErrWhere(tl, tl->t); - return; - } - - while (tl->t->tok == '*' || tl->t->tok == '/') { - tk = tl->t; - vcc_NextToken(tl); - vcc_expr4(tl, &e2, f2); - ERRCHK(tl); - assert(e2->fmt == f2); - if (tk->tok == '*') - *e = vcc_expr_edit(f3, "(\v1*\v2)", *e, e2); - else - *e = vcc_expr_edit(f3, "(\v1/\v2)", *e, e2); - } -} - -/*-------------------------------------------------------------------- - * SYNTAX: - * ExprAdd: - * ExprMul { {'+'|'-'} ExprMul } * - * - * For reasons of memory allocation/copying and general performance, - * STRINGs in VCL are quite special. Addition/concatenation is split - * into it's own subfunction to encapsulate this. - */ - -static void -vcc_expr_string_add(struct vcc *tl, struct expr **e) -{ - struct expr *e2; - enum var_type f2; - - f2 = (*e)->fmt; - - while (tl->t->tok == '+') { - vcc_NextToken(tl); - vcc_expr_mul(tl, &e2, STRING); - ERRCHK(tl); - if (e2->fmt != STRING && e2->fmt != STRING_LIST) - vcc_expr_tostring(&e2, f2); - ERRCHK(tl); - assert(e2->fmt == STRING || e2->fmt == STRING_LIST); - - if (vcc_isconst(*e) && vcc_isconst(e2)) { - assert((*e)->fmt == STRING); - assert(e2->fmt == STRING); - *e = vcc_expr_edit(STRING, "\v1\n\v2", *e, e2); - (*e)->constant = EXPR_CONST; - } else if (((*e)->constant & EXPR_STR_CONST) && - vcc_isconst(e2)) { - assert((*e)->fmt == STRING_LIST); - assert(e2->fmt == STRING); - *e = vcc_expr_edit(STRING_LIST, "\v1\n\v2", *e, e2); - (*e)->constant = EXPR_VAR | EXPR_STR_CONST; - } else if (e2->fmt == STRING && vcc_isconst(e2)) { - *e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2); - (*e)->constant = EXPR_VAR | EXPR_STR_CONST; - } else { - *e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2); - (*e)->constant = EXPR_VAR; - } - } -} - -static void -vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt) -{ - struct expr *e2; - enum var_type f2; - struct token *tk; - - *e = NULL; - vcc_expr_mul(tl, e, fmt); - ERRCHK(tl); - f2 = (*e)->fmt; - - /* Unless we specifically ask for a HEADER, fold them to string here */ - if (fmt != HEADER && f2 == HEADER) { - vcc_expr_tostring(e, STRING); - f2 = (*e)->fmt; - assert(f2 == STRING); - } - - if (tl->t->tok != '+' && tl->t->tok != '-') - return; - - switch(f2) { - case STRING: - case STRING_LIST: - vcc_expr_string_add(tl, e); - return; - case INT: break; - case TIME: break; - case DURATION: break; - case BYTES: break; - default: - VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n", - PF(tl->t), vcc_Type(f2)); - vcc_ErrWhere(tl, tl->t); - return; - } - - while (tl->t->tok == '+' || tl->t->tok == '-') { - if (f2 == TIME) - f2 = DURATION; - tk = tl->t; - vcc_NextToken(tl); - vcc_expr_mul(tl, &e2, f2); - ERRCHK(tl); - if (tk->tok == '-' && (*e)->fmt == TIME && e2->fmt == TIME) { - /* OK */ - } else if ((*e)->fmt == TIME && e2->fmt == DURATION) { - f2 = TIME; - /* OK */ - } else if (tk->tok == '-' && - (*e)->fmt == BYTES && e2->fmt == BYTES) { - /* OK */ - } else if (e2->fmt != f2) { - VSB_printf(tl->sb, "%s %.*s %s not possible.\n", - vcc_Type((*e)->fmt), PF(tk), vcc_Type(e2->fmt)); - vcc_ErrWhere2(tl, tk, tl->t); - return; - } - if (tk->tok == '+') - *e = vcc_expr_edit(f2, "(\v1+\v2)", *e, e2); - else if (f2 == TIME && e2->fmt == TIME) - *e = vcc_expr_edit(DURATION, "(\v1-\v2)", *e, e2); - else - *e = vcc_expr_edit(f2, "(\v1-\v2)", *e, e2); - } -} - -/*-------------------------------------------------------------------- - * Fold the STRING types correctly - */ - -static void -vcc_expr_strfold(struct vcc *tl, struct expr **e, enum var_type fmt) -{ - - vcc_expr_add(tl, e, fmt); - ERRCHK(tl); - - if (fmt != STRING_LIST && (*e)->fmt == STRING_LIST) - *e = vcc_expr_edit(STRING, - "\v+VRT_CollectString(ctx,\n\v1,\nvrt_magic_string_end)\v-", - *e, NULL); - if (fmt == STRING_LIST && (*e)->fmt == STRING) - (*e)->fmt = STRING_LIST; -} - -/*-------------------------------------------------------------------- - * SYNTAX: - * ExprCmp: - * ExprAdd - * ExprAdd Relation ExprAdd - * ExprAdd(STRING) '~' CString - * ExprAdd(STRING) '!~' CString - * ExprAdd(IP) '~' IP - * ExprAdd(IP) '!~' IP - */ - -#define NUM_REL(typ) \ - {typ, T_EQ, "(\v1 == \v2)" }, \ - {typ, T_NEQ, "(\v1 != \v2)" }, \ - {typ, T_LEQ, "(\v1 <= \v2)" }, \ - {typ, T_GEQ, "(\v1 >= \v2)" }, \ - {typ, '<', "(\v1 < \v2)" }, \ - {typ, '>', "(\v1 > \v2)" } - -static const struct cmps { - enum var_type fmt; - unsigned token; - const char *emit; -} vcc_cmps[] = { - NUM_REL(INT), - NUM_REL(DURATION), - NUM_REL(BYTES), - NUM_REL(REAL), - - {STRING, T_EQ, "!VRT_strcmp(\v1, \v2)" }, - {STRING, T_NEQ, "VRT_strcmp(\v1, \v2)" }, - - {VOID, 0, NULL} -}; - -#undef NUM_REL - -static void -vcc_expr_cmp(struct vcc *tl, struct expr **e, enum var_type fmt) -{ - struct expr *e2; - const struct cmps *cp; - char buf[256]; - const char *re; - const char *not; - struct token *tk; - - *e = NULL; - - vcc_expr_strfold(tl, e, fmt); - ERRCHK(tl); - - if ((*e)->fmt == BOOL) - return; - - tk = tl->t; - for (cp = vcc_cmps; cp->fmt != VOID; cp++) - if ((*e)->fmt == cp->fmt && tl->t->tok == cp->token) - break; - if (cp->fmt != VOID) { - vcc_NextToken(tl); - vcc_expr_strfold(tl, &e2, (*e)->fmt); - ERRCHK(tl); - if (e2->fmt != (*e)->fmt) { /* XXX */ - VSB_printf(tl->sb, "Comparison of different types: "); - VSB_printf(tl->sb, "%s ", vcc_Type((*e)->fmt)); - vcc_ErrToken(tl, tk); - VSB_printf(tl->sb, " %s\n", vcc_Type(e2->fmt)); - vcc_ErrWhere(tl, tk); - return; - } - *e = vcc_expr_edit(BOOL, cp->emit, *e, e2); - return; - } - if ((*e)->fmt == STRING && - (tl->t->tok == '~' || tl->t->tok == T_NOMATCH)) { - not = tl->t->tok == '~' ? "" : "!"; - vcc_NextToken(tl); - ExpectErr(tl, CSTR); - re = vcc_regexp(tl); - ERRCHK(tl); - vcc_NextToken(tl); - bprintf(buf, "%sVRT_re_match(ctx, \v1, %s)", not, re); - *e = vcc_expr_edit(BOOL, buf, *e, NULL); - return; - } - if ((*e)->fmt == IP && - (tl->t->tok == '~' || tl->t->tok == T_NOMATCH)) { - not = tl->t->tok == '~' ? "" : "!"; - vcc_NextToken(tl); - ExpectErr(tl, ID); - vcc_AddRef(tl, tl->t, SYM_ACL); - bprintf(buf, "%smatch_acl_named_%.*s(ctx, \v1)", - not, PF(tl->t)); - vcc_NextToken(tl); - *e = vcc_expr_edit(BOOL, buf, *e, NULL); - return; - } - if ((*e)->fmt == IP && (tl->t->tok == T_EQ || tl->t->tok == T_NEQ)) { - vcc_Acl_Hack(tl, buf); - *e = vcc_expr_edit(BOOL, buf, *e, NULL); - return; - } - if ((*e)->fmt == BACKEND && - (tl->t->tok == T_EQ || tl->t->tok == T_NEQ)) { - vcc_NextToken(tl); - ExpectErr(tl, ID); - vcc_AddRef(tl, tl->t, SYM_BACKEND); - bprintf(buf, "(\v1 %.*s VGCDIR(_%.*s))", PF(tk), PF(tl->t)); - vcc_NextToken(tl); - *e = vcc_expr_edit(BOOL, buf, *e, NULL); - return; - } - switch (tl->t->tok) { - case T_EQ: - case T_NEQ: - case '<': - case T_LEQ: - case '>': - case T_GEQ: - case '~': - case T_NOMATCH: - VSB_printf(tl->sb, "Operator %.*s not possible on %s\n", - PF(tl->t), vcc_Type((*e)->fmt)); - vcc_ErrWhere(tl, tl->t); - return; - default: - break; - } - if (fmt == BOOL && (*e)->fmt == STRING) { - *e = vcc_expr_edit(BOOL, "(\v1 != 0)", *e, NULL); - return; - } -} - -/*-------------------------------------------------------------------- - * SYNTAX: - * ExprNot: - * '!' ExprCmp - */ - -static void -vcc_expr_not(struct vcc *tl, struct expr **e, enum var_type fmt) -{ - struct expr *e2; - struct token *tk; - - *e = NULL; - if (fmt != BOOL || tl->t->tok != '!') { - vcc_expr_cmp(tl, e, fmt); - return; - } - - vcc_NextToken(tl); - tk = tl->t; - vcc_expr_cmp(tl, &e2, fmt); - ERRCHK(tl); - if (e2->fmt == BOOL) { - *e = vcc_expr_edit(BOOL, "!(\v1)", e2, NULL); - return; - } - VSB_printf(tl->sb, "'!' must be followed by BOOL, found "); - VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt)); - vcc_ErrWhere2(tl, tk, tl->t); -} - -/*-------------------------------------------------------------------- - * SYNTAX: - * ExprCand: - * ExprNot { '&&' ExprNot } * - */ - -static void -vcc_expr_cand(struct vcc *tl, struct expr **e, enum var_type fmt) -{ - struct expr *e2; - struct token *tk; - - *e = NULL; - vcc_expr_not(tl, e, fmt); - ERRCHK(tl); - if ((*e)->fmt != BOOL || tl->t->tok != T_CAND) - return; - *e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL); - while (tl->t->tok == T_CAND) { - vcc_NextToken(tl); - tk = tl->t; - vcc_expr_not(tl, &e2, fmt); - ERRCHK(tl); - if (e2->fmt != BOOL) { - VSB_printf(tl->sb, - "'&&' must be followed by BOOL, found "); - VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt)); - vcc_ErrWhere2(tl, tk, tl->t); - return; - } - *e = vcc_expr_edit(BOOL, "\v1\v-\n&&\v+\n\v2", *e, e2); - } - *e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL); -} - -/*-------------------------------------------------------------------- - * SYNTAX: - * Expr0: - * ExprCand { '||' ExprCand } * - */ - -static void -vcc_expr0(struct vcc *tl, struct expr **e, enum var_type fmt) -{ - struct expr *e2; - struct token *tk; - - *e = NULL; - vcc_expr_cand(tl, e, fmt); - ERRCHK(tl); - if ((*e)->fmt != BOOL || tl->t->tok != T_COR) - return; - *e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL); - while (tl->t->tok == T_COR) { - vcc_NextToken(tl); - tk = tl->t; - vcc_expr_cand(tl, &e2, fmt); - ERRCHK(tl); - if (e2->fmt != BOOL) { - VSB_printf(tl->sb, - "'||' must be followed by BOOL, found "); - VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt)); - vcc_ErrWhere2(tl, tk, tl->t); - return; - } - *e = vcc_expr_edit(BOOL, "\v1\v-\n||\v+\n\v2", *e, e2); - } - *e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL); -} - -/*-------------------------------------------------------------------- - * This function parses and emits the C-code to evaluate an expression - * - * We know up front what kind of type we want the expression to be, - * and this function is the backstop if that doesn't succeed. - */ - -void -vcc_Expr(struct vcc *tl, enum var_type fmt) -{ - struct expr *e; - struct token *t1; - - assert(fmt != VOID); - - t1 = tl->t; - vcc_expr0(tl, &e, fmt); - ERRCHK(tl); - if (fmt == STRING || fmt == STRING_LIST) - vcc_expr_tostring(&e, fmt); - if (!tl->err && fmt != e->fmt) { - VSB_printf(tl->sb, "Expression has type %s, expected %s\n", - vcc_Type(e->fmt), vcc_Type(fmt)); - tl->err = 1; - } - if (!tl->err) { - if (e->fmt == STRING_LIST) { - e = vcc_expr_edit(STRING_LIST, - "\v+\n\v1,\nvrt_magic_string_end\v-", e, NULL); - } - vcc_expr_fmt(tl->fb, tl->indent, e); - VSB_putc(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_SymFunc(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 -vcc_Expr_Init(struct vcc *tl) -{ - struct symbol *sym; - - sym = VCC_AddSymbolStr(tl, "regsub", SYM_FUNC); - AN(sym); - sym->eval = vcc_Eval_Regsub; - sym->eval_priv = NULL; - - sym = VCC_AddSymbolStr(tl, "regsuball", SYM_FUNC); - AN(sym); - sym->eval = vcc_Eval_Regsub; - sym->eval_priv = sym; - - sym = VCC_AddSymbolStr(tl, "true", SYM_FUNC); - AN(sym); - sym->eval = vcc_Eval_BoolConst; - sym->eval_priv = sym; - - sym = VCC_AddSymbolStr(tl, "false", SYM_FUNC); - AN(sym); - sym->eval = vcc_Eval_BoolConst; - sym->eval_priv = NULL; -} diff --git a/lib/libvcl/vcc_parse.c b/lib/libvcl/vcc_parse.c deleted file mode 100644 index ab562f5..0000000 --- a/lib/libvcl/vcc_parse.c +++ /dev/null @@ -1,359 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include -#include - -#include "vcc_compile.h" - -/*--------------------------------------------------------------------*/ - -static void vcc_Compound(struct vcc *tl); - -/*--------------------------------------------------------------------*/ - -#define L(tl, foo) do { \ - tl->indent += INDENT; \ - foo; \ - tl->indent -= INDENT; \ -} while (0) - -#define C(tl, sep) do { \ - Fb(tl, 1, "VRT_count(ctx, %u)%s\n", ++tl->cnt, sep); \ - tl->t->cnt = tl->cnt; \ -} while (0) - -/*-------------------------------------------------------------------- - * SYNTAX: - * Conditional: - * '(' Cond_0 ')' - */ - -static void -vcc_Conditional(struct vcc *tl) -{ - - SkipToken(tl, '('); - Fb(tl, 0, "(\n"); - L(tl, vcc_Expr(tl, BOOL)); - ERRCHK(tl); - Fb(tl, 1, ")\n"); - SkipToken(tl, ')'); -} - -/*-------------------------------------------------------------------- - * SYNTAX: - * IfStmt: - * 'if' Conditional Compound Branch1* Branch2 - * Branch1: - * 'elseif' Conditional Compound - * Branch2: - * 'else' Compound - * null - */ - -static void -vcc_IfStmt(struct vcc *tl) -{ - - SkipToken(tl, ID); - Fb(tl, 1, "if "); - vcc_Conditional(tl); - ERRCHK(tl); - L(tl, vcc_Compound(tl)); - ERRCHK(tl); - while (tl->t->tok == ID) { - if (vcc_IdIs(tl->t, "else")) { - vcc_NextToken(tl); - if (tl->t->tok == '{') { - Fb(tl, 1, "else\n"); - L(tl, vcc_Compound(tl)); - ERRCHK(tl); - return; - } - if (tl->t->tok != ID || !vcc_IdIs(tl->t, "if")) { - VSB_printf(tl->sb, - "'else' must be followed by 'if' or '{'\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - Fb(tl, 1, "else if "); - vcc_NextToken(tl); - vcc_Conditional(tl); - ERRCHK(tl); - L(tl, vcc_Compound(tl)); - ERRCHK(tl); - } else if (vcc_IdIs(tl->t, "elseif") || - vcc_IdIs(tl->t, "elsif") || - vcc_IdIs(tl->t, "elif")) { - Fb(tl, 1, "else if "); - vcc_NextToken(tl); - vcc_Conditional(tl); - ERRCHK(tl); - L(tl, vcc_Compound(tl)); - ERRCHK(tl); - } else { - break; - } - } - C(tl, ";"); -} - -/*-------------------------------------------------------------------- - * SYNTAX: - * Compound: - * '{' Stmt* '}' - * - * Stmt: - * Compound - * IfStmt - * CSRC - * Id(Action) (XXX) - */ - -static void -vcc_Compound(struct vcc *tl) -{ - int i; - - SkipToken(tl, '{'); - Fb(tl, 1, "{\n"); - tl->indent += INDENT; - C(tl, ";"); - while (1) { - ERRCHK(tl); - switch (tl->t->tok) { - case '{': - vcc_Compound(tl); - break; - case '}': - vcc_NextToken(tl); - tl->indent -= INDENT; - Fb(tl, 1, "}\n"); - return; - case CSRC: - if (tl->allow_inline_c) { - Fb(tl, 1, "%.*s\n", - (int) (tl->t->e - (tl->t->b + 2)), - tl->t->b + 1); - vcc_NextToken(tl); - } else { - VSB_printf(tl->sb, - "Inline-C not allowed\n"); - vcc_ErrWhere(tl, tl->t); - } - break; - case EOI: - VSB_printf(tl->sb, - "End of input while in compound statement\n"); - tl->err = 1; - return; - case ID: - if (vcc_IdIs(tl->t, "if")) { - vcc_IfStmt(tl); - break; - } else { - i = vcc_ParseAction(tl); - ERRCHK(tl); - if (i) { - SkipToken(tl, ';'); - break; - } - } - /* FALLTHROUGH */ - default: - /* We deliberately do not mention inline C */ - VSB_printf(tl->sb, - "Expected an action, 'if', '{' or '}'\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - } -} - -/*-------------------------------------------------------------------- - * SYNTAX: - * Function: - * 'sub' ID(name) Compound - */ - -static void -vcc_Function(struct vcc *tl) -{ - int m, i; - - vcc_NextToken(tl); - ExpectErr(tl, ID); - if (!vcc_isCid(tl->t)) { - VSB_printf(tl->sb, - "Names of VCL sub's cannot contain '-'\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - - m = IsMethod(tl->t); - if (m == -2) { - VSB_printf(tl->sb, - "VCL sub's named 'vcl*' are reserved names.\n"); - vcc_ErrWhere(tl, tl->t); - VSB_printf(tl->sb, "Valid vcl_* methods are:\n"); - for (i = 0; method_tab[i].name != NULL; i++) - VSB_printf(tl->sb, "\t%s\n", method_tab[i].name); - return; - } else if (m != -1) { - assert(m < VCL_MET_MAX); - tl->fb = tl->fm[m]; - if (tl->mprocs[m] == NULL) { - (void)vcc_AddDef(tl, tl->t, SYM_SUB); - vcc_AddRef(tl, tl->t, SYM_SUB); - tl->mprocs[m] = vcc_AddProc(tl, tl->t); - } - tl->curproc = tl->mprocs[m]; - Fb(tl, 1, " /* ... from "); - vcc_Coord(tl, tl->fb, NULL); - Fb(tl, 0, " */\n"); - } else { - tl->fb = tl->fc; - i = vcc_AddDef(tl, tl->t, SYM_SUB); - if (i > 1) { - VSB_printf(tl->sb, - "Function %.*s redefined\n", PF(tl->t)); - vcc_ErrWhere(tl, tl->t); - return; - } - tl->curproc = vcc_AddProc(tl, tl->t); - Fh(tl, 0, "static int VGC_function_%.*s " - "(struct vrt_ctx *ctx);\n", PF(tl->t)); - Fc(tl, 1, "\nstatic int __match_proto__(vcl_func_t)\n"); - Fc(tl, 1, "VGC_function_%.*s(struct vrt_ctx *ctx)\n", - PF(tl->t)); - } - vcc_NextToken(tl); - tl->indent += INDENT; - Fb(tl, 1, "{\n"); - L(tl, vcc_Compound(tl)); - if (m == -1) { - /* - * non-method subroutines must have an explicit non-action - * return in case they just fall through the bottom. - */ - Fb(tl, 1, " return(0);\n"); - } - Fb(tl, 1, "}\n"); - tl->indent -= INDENT; - tl->fb = NULL; - tl->curproc = NULL; -} - -/*-------------------------------------------------------------------- - */ - -static void -vcc_Director(struct vcc *tl) -{ - VSB_printf(tl->sb, "\ndirectors are now in directors VMOD.\n"); - vcc_ErrWhere(tl, tl->t); -} - -/*-------------------------------------------------------------------- - * Top level of parser, recognize: - * Inline C-code - * ACL definitions - * Function definitions - * Backend & Director definitions - * End of input - */ - -typedef void parse_f(struct vcc *tl); - -static struct toplev { - const char *name; - parse_f *func; -} toplev[] = { - { "acl", vcc_Acl }, - { "sub", vcc_Function }, - { "backend", vcc_ParseBackend }, - { "director", vcc_Director }, - { "probe", vcc_ParseProbe }, - { "import", vcc_ParseImport }, - { NULL, NULL } -}; - -void -vcc_Parse(struct vcc *tl) -{ - struct toplev *tp; - - while (tl->t->tok != EOI) { - ERRCHK(tl); - switch (tl->t->tok) { - case CSRC: - if (tl->allow_inline_c) { - Fc(tl, 0, "%.*s\n", - (int) (tl->t->e - (tl->t->b + 4)), - tl->t->b + 2); - vcc_NextToken(tl); - } else { - VSB_printf(tl->sb, - "Inline-C not allowed\n"); - vcc_ErrWhere(tl, tl->t); - } - break; - case EOI: - break; - case ID: - for (tp = toplev; tp->name != NULL; tp++) { - if (!vcc_IdIs(tl->t, tp->name)) - continue; - tp->func(tl); - break; - } - if (tp->name != NULL) - break; - /* FALLTHROUGH */ - default: - /* We deliberately do not mention inline-C */ - VSB_printf(tl->sb, "Expected one of\n\t"); - for (tp = toplev; tp->name != NULL; tp++) { - if (tp[1].name == NULL) - VSB_printf(tl->sb, " or "); - VSB_printf(tl->sb, "'%s'", tp->name); - if (tp[1].name != NULL) - VSB_printf(tl->sb, ", "); - } - VSB_printf(tl->sb, "\nFound: "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, " at\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - } -} diff --git a/lib/libvcl/vcc_storage.c b/lib/libvcl/vcc_storage.c deleted file mode 100644 index 5f9712a..0000000 --- a/lib/libvcl/vcc_storage.c +++ /dev/null @@ -1,149 +0,0 @@ -/*- - * Copyright (c) 2010 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * All stuff related to the storage.* part of the namespace. - * - * "All" is actually only a wildcard function, which instantiates variables - * on demand under the storage.* tree of the namespace. - * - * About the syntax: - * ----------------- - * - * One of our long term goals is to have dynamic storage configuration, such - * as the ability to add or remove a stevedore on the fly, without restarting - * the worker process. - * - * Even though this goal is far out in the future, it influences the syntax - * design of storage selection from VCL. - * - * In difference from backends, where we know the possible set of backends at - * compile time, we will not in the future know the identity of the stevedores - * available at compile time, so we have to rely on VRT name resolution. - * - * This indicates a namespace on the form storage.. - * - * For each property, we must define a default value if the named stevedore - * does not exists, such that for instance stevedore.forgetit.freespace - * returns zero etc. - * - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "vcc_compile.h" - -#define PFX "storage." - -/*-------------------------------------------------------------------- - * - */ - -static struct var * -vcc_Stv_mkvar(struct vcc *tl, const struct token *t, enum var_type fmt) -{ - struct var *v; - - v = TlAlloc(tl, sizeof *v); - AN(v); - - v->name = TlDupTok(tl, t); - v->r_methods = 0 -#define VCL_MET_MAC(l,u,b) | VCL_MET_##u -#include "tbl/vcl_returns.h" -#undef VCL_MET_MAC - ; - v->fmt = fmt; - - return (v); -} - -static struct stvars { - const char *name; - enum var_type fmt; -} stvars[] = { -#define VRTSTVVAR(nm, vtype, ctype, dval) { #nm, vtype }, -#include "tbl/vrt_stv_var.h" -#undef VRTSTVVAR - { NULL, BOOL } -}; - -struct symbol * -vcc_Stv_Wildcard(struct vcc *tl, const struct token *t, - const struct symbol *wcsym) -{ - const char *p, *q; - struct var *v = NULL; - struct symbol *sym; - struct stvars *sv; - char stv[1024]; - char buf[1024]; - - (void)wcsym; - assert((t->e - t->b) > strlen(PFX)); - assert(!memcmp(t->b, PFX, strlen(PFX))); - - p = t->b + strlen(PFX); - for (q = p; q < t->e && *q != '.'; q++) - continue; - bprintf(stv, "%.*s", (int)(q - p), p); - - if (q == t->e) { - v = vcc_Stv_mkvar(tl, t, BOOL); - bprintf(buf, "VRT_Stv(\"%s\")", stv); - v->rname = TlDup(tl, buf); - } else { - assert(*q == '.'); - q++; - for(sv = stvars; sv->name != NULL; sv++) { - if (strncmp(q, sv->name, t->e - q)) - continue; - if (sv->name[t->e - q] != '\0') - continue; - v = vcc_Stv_mkvar(tl, t, sv->fmt); - bprintf(buf, "VRT_Stv_%s(\"%s\")", sv->name, stv); - v->rname = TlDup(tl, buf); - break; - } - } - - if (v == NULL) - return (NULL); - - sym = VCC_AddSymbolTok(tl, t, SYM_VAR); - AN(sym); - sym->var = v; - sym->fmt = v->fmt; - sym->eval = vcc_Eval_Var; - sym->r_methods = v->r_methods; - - return (sym); -} diff --git a/lib/libvcl/vcc_symb.c b/lib/libvcl/vcc_symb.c deleted file mode 100644 index c3d8a13..0000000 --- a/lib/libvcl/vcc_symb.c +++ /dev/null @@ -1,142 +0,0 @@ -/*- - * Copyright (c) 2010 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include -#include -#include - -#include "vcc_compile.h" - -/*--------------------------------------------------------------------*/ - -const char * -VCC_SymKind(struct vcc *tl, const struct symbol *s) -{ - switch(s->kind) { -#define VCC_SYMB(uu, ll) case SYM_##uu: return(#ll); -#include "tbl/symbol_kind.h" -#undef VCC_SYMB - default: - ErrInternal(tl); - VSB_printf(tl->sb, "Symbol Kind 0x%x\n", s->kind); - return("INTERNALERROR"); - } -} - - -static struct symbol * -vcc_AddSymbol(struct vcc *tl, const char *nb, int l, enum symkind kind) -{ - struct symbol *sym; - - VTAILQ_FOREACH(sym, &tl->symbols, list) { - if (sym->nlen != l) - continue; - if (memcmp(nb, sym->name, l)) - continue; - if (kind != sym->kind) - continue; - VSB_printf(tl->sb, "Name Collision: <%.*s> <%s>\n", - l, nb, VCC_SymKind(tl, sym)); - ErrInternal(tl); - return (NULL); - } - ALLOC_OBJ(sym, SYMBOL_MAGIC); - AN(sym); - sym->name = malloc(l + 1L); - AN(sym->name); - memcpy(sym->name, nb, l); - sym->name[l] = '\0'; - sym->nlen = l; - VTAILQ_INSERT_HEAD(&tl->symbols, sym, list); - sym->kind = kind; - return (sym); -} - -struct symbol * -VCC_AddSymbolStr(struct vcc *tl, const char *name, enum symkind kind) -{ - - return (vcc_AddSymbol(tl, name, strlen(name), kind)); -} - -struct symbol * -VCC_AddSymbolTok(struct vcc *tl, const struct token *t, enum symkind kind) -{ - - return (vcc_AddSymbol(tl, t->b, t->e - t->b, kind)); -} - -struct symbol * -VCC_GetSymbolTok(struct vcc *tl, const struct token *tok, enum symkind kind) -{ - struct symbol *sym; - - sym = VCC_FindSymbol(tl, tok, kind); - if (sym == NULL) { - sym = vcc_AddSymbol(tl, tok->b, tok->e - tok->b, kind); - AN(sym); - sym->def_b = tok; - } - return (sym); -} - -struct symbol * -VCC_FindSymbol(struct vcc *tl, const struct token *t, enum symkind kind) -{ - struct symbol *sym; - - assert(t->tok == ID); - VTAILQ_FOREACH(sym, &tl->symbols, list) { - if (sym->kind == SYM_WILDCARD && - (t->e - t->b > sym->nlen) && - !memcmp(sym->name, t->b, sym->nlen)) { - AN(sym->wildcard); - return (sym->wildcard(tl, t, sym)); - } - if (kind != SYM_NONE && kind != sym->kind) - continue; - if (vcc_IdIs(t, sym->name)) - return (sym); - } - return (NULL); -} - -void -VCC_WalkSymbols(struct vcc *tl, symwalk_f *func, enum symkind kind) -{ - struct symbol *sym; - - VTAILQ_FOREACH(sym, &tl->symbols, list) { - if (kind == SYM_NONE || kind == sym->kind) - func(tl, sym); - ERRCHK(tl); - } -} diff --git a/lib/libvcl/vcc_token.c b/lib/libvcl/vcc_token.c deleted file mode 100644 index 6201fea..0000000 --- a/lib/libvcl/vcc_token.c +++ /dev/null @@ -1,523 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "vcc_compile.h" - -/*--------------------------------------------------------------------*/ - -void -vcc_ErrToken(const struct vcc *tl, const struct token *t) -{ - - if (t->tok == EOI) - VSB_printf(tl->sb, "end of input"); - else if (t->tok == CSRC) - VSB_printf(tl->sb, "C{ ... }C"); - else - VSB_printf(tl->sb, "'%.*s'", PF(t)); -} - -void -vcc__ErrInternal(struct vcc *tl, const char *func, unsigned line) -{ - - VSB_printf(tl->sb, "VCL compiler internal error at %s():%u\n", - func, line); - tl->err = 1; -} - -/*-------------------------------------------------------------------- - * Find start of source-line of token - */ - -static void -vcc_iline(const struct token *t, const char **ll, int tail) -{ - const char *p, *b, *x; - - b = t->src->b; - if (ll != NULL) - *ll = b; - x = tail ? t->e - 1 : t->b; - for (p = b; p < x; p++) { - if (*p == '\n') { - if (ll != NULL) - *ll = p + 1; - } - } -} - -/*-------------------------------------------------------------------- - * Find and print src+line+pos of this token - */ - -static void -vcc_icoord(struct vsb *vsb, const struct token *t, int tail) -{ - unsigned lin, pos; - const char *p, *b, *x; - - lin = 1; - pos = 0; - b = t->src->b; - x = tail ? t->e - 1 : t->b; - for (p = b; p < x; p++) { - if (*p == '\n') { - lin++; - pos = 0; - } else if (*p == '\t') { - pos &= ~7; - pos += 8; - } else - pos++; - } - VSB_printf(vsb, "('%s' Line %u Pos %u)", t->src->name, lin, pos + 1); -} - -/*--------------------------------------------------------------------*/ - -void -vcc_Coord(const struct vcc *tl, struct vsb *vsb, const struct token *t) -{ - - if (t == NULL) - t = tl->t; - vcc_icoord(vsb, t, 0); -} - -/*-------------------------------------------------------------------- - * Output one line of source code, starting at 'l' and ending at the - * first NL or 'le'. - */ - -static void -vcc_quoteline(const struct vcc *tl, const char *l, const char *le) -{ - const char *p; - unsigned x, y; - - x = y = 0; - for (p = l; p < le && *p != '\n'; p++) { - if (*p == '\t') { - y &= ~7; - y += 8; - while (x < y) { - VSB_bcat(tl->sb, " ", 1); - x++; - } - } else { - x++; - y++; - VSB_bcat(tl->sb, p, 1); - } - } - VSB_putc(tl->sb, '\n'); -} - -/*-------------------------------------------------------------------- - * Output a marker line for a sourceline starting at 'l' and ending at - * the first NL or 'le'. Characters between 'b' and 'e' are marked. - */ - -static void -vcc_markline(const struct vcc *tl, const char *l, const char *le, - const char *b, const char *e) -{ - const char *p; - unsigned x, y; - char c; - - x = y = 0; - for (p = l; p < le && *p != '\n'; p++) { - if (p >= b && p < e) - c = '#'; - else - c = '-'; - - if (*p == '\t') { - y &= ~7; - y += 8; - } else - y++; - while (x < y) { - VSB_putc(tl->sb, c); - x++; - } - } - VSB_putc(tl->sb, '\n'); -} - -/*--------------------------------------------------------------------*/ -/* XXX: should take first+last token */ - -void -vcc_ErrWhere2(struct vcc *tl, const struct token *t, const struct token *t2) -{ - const char *l1, *l2, *l3; - - if (t == NULL) { - vcc_ErrWhere(tl, t2); - return; - } - vcc_iline(t, &l1, 0); - t2 = VTAILQ_PREV(t2, tokenhead, list); - vcc_iline(t2, &l2, 1); - - - if (l1 == l2) { - vcc_icoord(tl->sb, t, 0); - VSB_cat(tl->sb, " -- "); - vcc_icoord(tl->sb, t2, 1); - VSB_putc(tl->sb, '\n'); - /* Two tokens on same line */ - vcc_quoteline(tl, l1, t->src->e); - vcc_markline(tl, l1, t->src->e, t->b, t2->e); - } else { - /* Two tokens different lines */ - l3 = strchr(l1, '\n'); - AN(l3); - /* XXX: t had better be before t2 */ - vcc_icoord(tl->sb, t, 0); - if (l3 + 1 == l2) { - VSB_cat(tl->sb, " -- "); - vcc_icoord(tl->sb, t2, 1); - } - VSB_putc(tl->sb, '\n'); - vcc_quoteline(tl, l1, t->src->e); - vcc_markline(tl, l1, t->src->e, t->b, t2->e); - if (l3 + 1 != l2) { - VSB_cat(tl->sb, "[...]\n"); - vcc_icoord(tl->sb, t2, 1); - VSB_putc(tl->sb, '\n'); - } - vcc_quoteline(tl, l2, t->src->e); - vcc_markline(tl, l2, t->src->e, t->b, t2->e); - } - VSB_putc(tl->sb, '\n'); - tl->err = 1; -} - -void -vcc_ErrWhere(struct vcc *tl, const struct token *t) -{ - const char *l1; - - vcc_iline(t, &l1, 0); - vcc_icoord(tl->sb, t, 0); - VSB_putc(tl->sb, '\n'); - vcc_quoteline(tl, l1, t->src->e); - vcc_markline(tl, l1, t->src->e, t->b, t->e); - VSB_putc(tl->sb, '\n'); - tl->err = 1; -} - -/*--------------------------------------------------------------------*/ - -void -vcc_NextToken(struct vcc *tl) -{ - - tl->t = VTAILQ_NEXT(tl->t, list); - if (tl->t == NULL) { - VSB_printf(tl->sb, - "Ran out of input, something is missing or" - " maybe unbalanced (...) or {...}\n"); - tl->err = 1; - return; - } -} - -void -vcc__Expect(struct vcc *tl, unsigned tok, unsigned line) -{ - if (tl->t->tok == tok) - return; - VSB_printf(tl->sb, "Expected %s got ", vcl_tnames[tok]); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, "\n(program line %u), at\n", line); - vcc_ErrWhere(tl, tl->t); -} - -/*-------------------------------------------------------------------- - * Compare ID token to string, return true of match - */ - -int -vcc_IdIs(const struct token *t, const char *p) -{ - const char *q; - - assert(t->tok == ID); - for (q = t->b; q < t->e && *p != '\0'; p++, q++) - if (*q != *p) - return (0); - if (q != t->e || *p != '\0') - return (0); - return (1); -} - -/*-------------------------------------------------------------------- - * Check that we have a C-identifier - */ - -int -vcc_isCid(const struct token *t) -{ - const char *q; - - assert(t->tok == ID); - for (q = t->b; q < t->e; q++) { - if (!isalnum(*q) && *q != '_') - return (0); - } - return (1); -} - -void -vcc_ExpectCid(struct vcc *tl) -{ - - ExpectErr(tl, ID); - ERRCHK(tl); - if (vcc_isCid(tl->t)) - return; - VSB_printf(tl->sb, "Identifier "); - vcc_ErrToken(tl, tl->t); - VSB_printf(tl->sb, - " contains illegal characters, use [0-9a-zA-Z_] only.\n"); - vcc_ErrWhere(tl, tl->t); -} - -/*-------------------------------------------------------------------- - * Decode a string - */ - -static int -vcc_decstr(struct vcc *tl) -{ - char *q; - unsigned int l; - - assert(tl->t->tok == CSTR); - l = (tl->t->e - tl->t->b) - 2; - tl->t->dec = TlAlloc(tl, l + 1); - assert(tl->t->dec != NULL); - q = tl->t->dec; - memcpy(q, tl->t->b + 1, l); - q[l] = '\0'; - return (0); -} - -/*-------------------------------------------------------------------- - * Add a token to the token list. - */ - -void -vcc_AddToken(struct vcc *tl, unsigned tok, const char *b, const char *e) -{ - struct token *t; - - t = TlAlloc(tl, sizeof *t); - assert(t != NULL); - t->tok = tok; - t->b = b; - t->e = e; - t->src = tl->src; - if (tl->t != NULL) - VTAILQ_INSERT_AFTER(&tl->tokens, tl->t, t, list); - else - VTAILQ_INSERT_TAIL(&tl->tokens, t, list); - tl->t = t; -} - -/*-------------------------------------------------------------------- - * Lexical analysis and token generation - */ - -void -vcc_Lexer(struct vcc *tl, struct source *sp) -{ - const char *p, *q; - unsigned u; - - tl->src = sp; - for (p = sp->b; p < sp->e; ) { - - /* Skip any whitespace */ - if (isspace(*p)) { - p++; - continue; - } - - /* Skip '#.*\n' comments */ - if (*p == '#') { - while (p < sp->e && *p != '\n') - p++; - continue; - } - - /* Skip C-style comments */ - if (*p == '/' && p[1] == '*') { - for (q = p + 2; q < sp->e; q++) { - if (*q == '/' && q[1] == '*') { - VSB_printf(tl->sb, - "/* ... */ comment contains /*\n"); - vcc_AddToken(tl, EOI, p, p + 2); - vcc_ErrWhere(tl, tl->t); - vcc_AddToken(tl, EOI, q, q + 2); - vcc_ErrWhere(tl, tl->t); - return; - } - if (*q == '*' && q[1] == '/') { - p = q + 2; - break; - } - } - if (q < sp->e) - continue; - vcc_AddToken(tl, EOI, p, p + 2); - VSB_printf(tl->sb, - "Unterminated /* ... */ comment, starting at\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - - /* Skip C++-style comments */ - if (*p == '/' && p[1] == '/') { - while (p < sp->e && *p != '\n') - p++; - continue; - } - - /* Recognize inline C-code */ - if (*p == 'C' && p[1] == '{') { - for (q = p + 2; q < sp->e; q++) { - if (*q == '}' && q[1] == 'C') { - vcc_AddToken(tl, CSRC, p, q + 2); - break; - } - } - if (q < sp->e) { - p = q + 2; - continue; - } - vcc_AddToken(tl, EOI, p, p + 2); - VSB_printf(tl->sb, - "Unterminated inline C source, starting at\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - - /* Recognize long-strings */ - if (*p == '{' && p[1] == '"') { - for (q = p + 2; q < sp->e; q++) { - if (*q == '"' && q[1] == '}') { - vcc_AddToken(tl, CSTR, p, q + 2); - break; - } - } - if (q < sp->e) { - p = q + 2; - u = tl->t->e - tl->t->b; - u -= 4; /* {" ... "} */ - tl->t->dec = TlAlloc(tl, u + 1 ); - AN(tl->t->dec); - memcpy(tl->t->dec, tl->t->b + 2, u); - tl->t->dec[u] = '\0'; - continue; - } - vcc_AddToken(tl, EOI, p, p + 2); - VSB_printf(tl->sb, - "Unterminated long-string, starting at\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - - /* Match for the fixed tokens (see token.tcl) */ - u = vcl_fixed_token(p, &q); - if (u != 0) { - vcc_AddToken(tl, u, p, q); - p = q; - continue; - } - - /* Match strings */ - if (*p == '"') { - for (q = p + 1; q < sp->e; q++) { - if (*q == '"') { - q++; - break; - } - if (*q == '\r' || *q == '\n') { - vcc_AddToken(tl, EOI, p, q); - VSB_printf(tl->sb, - "Unterminated string at\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - } - vcc_AddToken(tl, CSTR, p, q); - if (vcc_decstr(tl)) - return; - p = q; - continue; - } - - /* Match Identifiers */ - if (isident1(*p)) { - for (q = p; q < sp->e; q++) - if (!isvar(*q)) - break; - vcc_AddToken(tl, ID, p, q); - p = q; - continue; - } - - /* Match numbers { [0-9]+ } */ - if (isdigit(*p)) { - for (q = p; q < sp->e; q++) - if (!isdigit(*q)) - break; - vcc_AddToken(tl, CNUM, p, q); - p = q; - continue; - } - vcc_AddToken(tl, EOI, p, p + 1); - VSB_printf(tl->sb, "Syntax error at\n"); - vcc_ErrWhere(tl, tl->t); - return; - } -} diff --git a/lib/libvcl/vcc_utils.c b/lib/libvcl/vcc_utils.c deleted file mode 100644 index 5870af5..0000000 --- a/lib/libvcl/vcc_utils.c +++ /dev/null @@ -1,255 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2013 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include -#include -#include -#include -#include - -#include "vcc_compile.h" - -#include "vre.h" -#include "vrt.h" -#include "vsa.h" - -/*--------------------------------------------------------------------*/ - -const char * -vcc_regexp(struct vcc *tl) -{ - char buf[BUFSIZ], *p; - vre_t *t; - const char *error; - int erroroffset; - - Expect(tl, CSTR); - if (tl->err) - return (NULL); - memset(&t, 0, sizeof t); - t = VRE_compile(tl->t->dec, 0, &error, &erroroffset); - if (t == NULL) { - VSB_printf(tl->sb, - "Regexp compilation error:\n\n%s\n\n", error); - vcc_ErrWhere(tl, tl->t); - return (NULL); - } - VRE_free(&t); - sprintf(buf, "VGC_re_%u", tl->unique++); - p = TlAlloc(tl, strlen(buf) + 1); - strcpy(p, buf); - - Fh(tl, 0, "static void *%s;\n", buf); - Fi(tl, 0, "\tVRT_re_init(&%s, ",buf); - EncToken(tl->fi, tl->t); - Fi(tl, 0, ");\n"); - Ff(tl, 0, "\tVRT_re_fini(%s);\n", buf); - return (p); -} - -/* - * The IPv6 crew royally screwed up the entire idea behind - * struct sockaddr, and combined with various other incomptency - * in the OS business, that means that there is no sane or even - * remotely portable way to initialize a sockaddr at compile time. - * - * In our case it is slightly more tricky than that, because we don't - * even want to #include the struct sockaddr* definitions. - * - * Instead we make sure the sockaddr is sane (for our values of sane) - * and dump it in binary, using a 64 bit integertype, hoping that this - * will ensure good enough alignment. - */ - -static const char * -vcc_sockaddr(struct vcc *tl, const void *sa, unsigned sal) -{ - unsigned n = (sal + 7) / 8, len; - uint64_t b[n]; - char *p; - - assert(VSA_Sane(sa)); - AN(sa); - AN(sal); - assert(sal < sizeof(struct sockaddr_storage)); - assert(sizeof(unsigned long long) == 8); - - p = TlAlloc(tl, 20); - sprintf(p, "sockaddr_%u", tl->unique++); - - Fh(tl, 0, "static const unsigned long long"); - Fh(tl, 0, " %s[%d] = {\n", p, n); - memcpy(b, sa, sal); - for (len = 0; len sb, - "%s '%.*s' could not be resolved to an IP address:\n", - errid, PF(t_err)); - VSB_printf(tl->sb, - "\t%s\n" - "(Sorry if that error message is gibberish.)\n", - gai_strerror(error)); - vcc_ErrWhere(tl, t_err); - return; - } - - for (res = res0; res; res = res->ai_next) { - for (pp = protos; pp->name != NULL; pp++) - if (res->ai_family == pp->family) - break; - if (pp->name == NULL) { - /* Unknown proto, ignore */ - continue; - } - if (pp->l == res->ai_addrlen && - !memcmp(&pp->sa, res->ai_addr, pp->l)) { - /* - * Same address we already emitted. - * This can happen using /etc/hosts - */ - continue; - } - - if (pp->l != 0 || retval == maxips) { - VSB_printf(tl->sb, - "%s %.*s: resolves to too many addresses.\n" - "Only one IPv4 %s IPv6 are allowed.\n" - "Please specify which exact address " - "you want to use, we found all of these:\n", - errid, PF(t_err), - maxips > 1 ? "and one" : "or"); - for (res1 = res0; res1 != NULL; res1 = res1->ai_next) { - error = getnameinfo(res1->ai_addr, - res1->ai_addrlen, hbuf, sizeof hbuf, - NULL, 0, NI_NUMERICHOST); - AZ(error); - VSB_printf(tl->sb, "\t%s\n", hbuf); - } - freeaddrinfo(res0); - vcc_ErrWhere(tl, t_err); - return; - } - - pp->l = res->ai_addrlen; - assert(pp->l < sizeof(struct sockaddr_storage)); - memcpy(&pp->sa, res->ai_addr, pp->l); - - error = getnameinfo(res->ai_addr, res->ai_addrlen, - hbuf, sizeof hbuf, NULL, 0, NI_NUMERICHOST); - AZ(error); - - Fh(tl, 0, "\n/* \"%s\" -> %s */\n", host, hbuf); - *(pp->dst) = vcc_sockaddr(tl, &pp->sa, pp->l); - if (pp->dst_ascii != NULL) { - *pp->dst_ascii = TlDup(tl, hbuf); - } - retval++; - } - if (p_ascii != NULL) { - error = getnameinfo(res0->ai_addr, - res0->ai_addrlen, NULL, 0, hbuf, sizeof hbuf, - NI_NUMERICSERV); - AZ(error); - *p_ascii = TlDup(tl, hbuf); - } - if (retval == 0) { - VSB_printf(tl->sb, - "%s '%.*s': resolves to " - "neither IPv4 nor IPv6 addresses.\n", - errid, PF(t_err) ); - vcc_ErrWhere(tl, t_err); - } -} diff --git a/lib/libvcl/vcc_var.c b/lib/libvcl/vcc_var.c deleted file mode 100644 index 74713b8..0000000 --- a/lib/libvcl/vcc_var.c +++ /dev/null @@ -1,134 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include -#include - -#include "vcc_compile.h" -#include "vct.h" - -/*--------------------------------------------------------------------*/ - -struct symbol * -vcc_Var_Wildcard(struct vcc *tl, const struct token *t, const struct symbol *wc) -{ - struct symbol *sym; - struct var *v; - const struct var *vh; - int l, i; - char c; - char buf[258]; - char cnam[256]; - - vh = wc->var; - - v = TlAlloc(tl, sizeof *v); - AN(v); - - assert(vh->fmt == HEADER); - v->name = TlDupTok(tl, t); - v->r_methods = vh->r_methods; - v->w_methods = vh->w_methods; - v->fmt = vh->fmt; - - /* Create a C-name version of the header name */ - l = strlen(v->name + vh->len) + 1; - for (i = 0; i < l - 1; i++) { - c = *(v->name + vh->len + i); - if (vct_isalpha(c) || vct_isdigit(c)) - cnam[i] = c; - else - cnam[i] = '_'; - } - cnam[i] = '\0'; - - /* Create the static identifier */ - Fh(tl, 0, "static const struct gethdr_s VGC_%s_%s =\n", - vh->rname, cnam); - Fh(tl, 0, " { %s, \"\\%03o%s:\"};\n", - vh->rname, (unsigned)l, v->name + vh->len); - - bprintf(buf, "&VGC_%s_%s", vh->rname, cnam); - v->rname = TlDup(tl, buf); - bprintf(buf, "VRT_SetHdr(ctx, %s, ", v->rname); - v->lname = TlDup(tl, buf); - - sym = VCC_AddSymbolTok(tl, t, SYM_VAR); - AN(sym); - sym->var = v; - sym->fmt = v->fmt; - sym->eval = vcc_Eval_Var; - sym->r_methods = v->r_methods; - return (sym); -} - -/*--------------------------------------------------------------------*/ - -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); - } - return (v); - } - VSB_printf(tl->sb, "Unknown variable "); - vcc_ErrToken(tl, t); - VSB_cat(tl->sb, "\nAt: "); - vcc_ErrWhere(tl, t); - return (NULL); -} diff --git a/lib/libvcl/vcc_vmod.c b/lib/libvcl/vcc_vmod.c deleted file mode 100644 index 7eb9d32c..0000000 --- a/lib/libvcl/vcc_vmod.c +++ /dev/null @@ -1,204 +0,0 @@ -/*- - * Copyright (c) 2010-2013 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include -#include -#include - -#include "vcc_compile.h" - -#include "vmod_abi.h" - -void -vcc_ParseImport(struct vcc *tl) -{ - void *hdl; - char fn[1024]; - char buf[256]; - struct token *mod, *t1; - const char *modname; - const char *proto; - const char *abi; - const char **spec; - struct symbol *sym; - const struct symbol *osym; - const char *p; - // int *modlen; - - t1 = tl->t; - SkipToken(tl, ID); /* "import" */ - - ExpectErr(tl, ID); - mod = tl->t; - vcc_NextToken(tl); - - osym = VCC_FindSymbol(tl, mod, SYM_NONE); - if (osym != NULL && osym->kind != SYM_VMOD) { - VSB_printf(tl->sb, "Module %.*s conflics with other symbol.\n", - PF(mod)); - vcc_ErrWhere2(tl, t1, tl->t); - return; - } - if (osym != NULL) { - VSB_printf(tl->sb, "Module %.*s already imported.\n", - PF(mod)); - vcc_ErrWhere2(tl, t1, tl->t); - VSB_printf(tl->sb, "Previous import was here:\n"); - vcc_ErrWhere2(tl, osym->def_b, osym->def_e); - return; - } - - bprintf(fn, "%.*s", PF(mod)); - sym = VCC_AddSymbolStr(tl, fn, SYM_VMOD); - ERRCHK(tl); - AN(sym); - sym->def_b = t1; - sym->def_e = tl->t; - - if (tl->t->tok == ID) { - if (!tl->unsafe_path) { - VSB_printf(tl->sb, - "'import ... from path...'" - " not allowed.\nAt:"); - vcc_ErrToken(tl, tl->t); - vcc_ErrWhere(tl, tl->t); - return; - } - if (!vcc_IdIs(tl->t, "from")) { - VSB_printf(tl->sb, "Expected 'from path...'\n"); - vcc_ErrWhere(tl, tl->t); - return; - } - vcc_NextToken(tl); - ExpectErr(tl, CSTR); - bprintf(fn, "%s", tl->t->dec); - vcc_NextToken(tl); - } else { - bprintf(fn, "%s/libvmod_%.*s.so", tl->vmod_dir, PF(mod)); - } - - Fh(tl, 0, "static void *VGC_vmod_%.*s;\n", PF(mod)); - - Fi(tl, 0, "\tif (VRT_Vmod_Init(&VGC_vmod_%.*s,\n", PF(mod)); - Fi(tl, 0, "\t &Vmod_%.*s_Func,\n", PF(mod)); - Fi(tl, 0, "\t sizeof(Vmod_%.*s_Func),\n", PF(mod)); - Fi(tl, 0, "\t \"%.*s\",\n", PF(mod)); - Fi(tl, 0, "\t "); - EncString(tl->fi, fn, NULL, 0); - Fi(tl, 0, ",\n\t "); - Fi(tl, 0, "cli))\n"); - Fi(tl, 0, "\t\treturn(1);\n"); - - SkipToken(tl, ';'); - - hdl = dlopen(fn, RTLD_NOW | RTLD_LOCAL); - if (hdl == NULL) { - VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", - PF(mod), fn, dlerror()); - vcc_ErrWhere(tl, mod); - return; - } - - bprintf(buf, "Vmod_%.*s_Name", PF(mod)); - modname = dlsym(hdl, buf); - if (modname == NULL) { - VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", - PF(mod), fn, "Symbol Vmod_Name not found"); - vcc_ErrWhere(tl, mod); - return; - } - if (!vcc_IdIs(mod, modname)) { - VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n", - PF(mod), fn); - VSB_printf(tl->sb, "\tModule has wrong name: <%s>\n", modname); - vcc_ErrWhere(tl, mod); - return; - } - - bprintf(buf, "Vmod_%.*s_ABI", PF(mod)); - abi = dlsym(hdl, buf); - if (abi == NULL || strcmp(abi, VMOD_ABI_Version) != 0) { - VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n", - PF(mod), fn); - VSB_printf(tl->sb, "\tABI mismatch, expected <%s>, got <%s>\n", - VMOD_ABI_Version, abi); - vcc_ErrWhere(tl, mod); - return; - } - - bprintf(buf, "Vmod_%.*s_Proto", PF(mod)); - proto = dlsym(hdl, buf); - if (proto == NULL) { - VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", - PF(mod), fn, "Symbol Vmod_Proto not found"); - vcc_ErrWhere(tl, mod); - return; - } - bprintf(buf, "Vmod_%.*s_Spec", PF(mod)); - spec = dlsym(hdl, buf); - if (spec == NULL) { - VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n", - PF(mod), fn, "Symbol Vmod_Spec not found"); - vcc_ErrWhere(tl, mod); - return; - } - Fh(tl, 0, "static struct vmod_priv vmod_priv_%.*s;\n", PF(mod)); - for (; *spec != NULL; spec++) { - p = *spec; - if (!strcmp(p, "OBJ")) { - p += strlen(p) + 1; - sym = VCC_AddSymbolStr(tl, p, SYM_OBJECT); - XXXAN(sym); - sym->args = p; - } else if (!strcmp(p, "INIT")) { - p += strlen(p) + 1; - Fi(tl, 0, "\t%s(&vmod_priv_%.*s, &VCL_conf);\n", - p, PF(mod)); - } else { - sym = VCC_AddSymbolStr(tl, p, SYM_FUNC); - ERRCHK(tl); - AN(sym); - sym->eval = vcc_Eval_SymFunc; - p += strlen(p) + 1; - sym->cfunc = p; - p += strlen(p) + 1; - sym->args = p; - - /* Functions which return VOID are procedures */ - if (!memcmp(p, "VOID\0", 5)) - sym->kind = SYM_PROC; - } - } - Fh(tl, 0, "\n%s\n", proto); - - /* XXX: zero the function pointer structure ?*/ - Ff(tl, 0, "\tvmod_priv_fini(&vmod_priv_%.*s);\n", PF(mod)); - Ff(tl, 0, "\tVRT_Vmod_Fini(&VGC_vmod_%.*s);\n", PF(mod)); -} diff --git a/lib/libvcl/vcc_xref.c b/lib/libvcl/vcc_xref.c deleted file mode 100644 index c3ef375..0000000 --- a/lib/libvcl/vcc_xref.c +++ /dev/null @@ -1,388 +0,0 @@ -/*- - * Copyright (c) 2006 Verdens Gang AS - * Copyright (c) 2006-2011 Varnish Software AS - * All rights reserved. - * - * Author: Poul-Henning Kamp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file contains code for two cross-reference or consistency checks. - * - * The first check is simply that all subroutine, acls and backends are - * both defined and referenced. Complaints about referenced but undefined - * or defined but unreferenced objects will be emitted. - * - * The second check recursively decends through subroutine calls to make - * sure that action actions are correct for the methods through which - * they are called. - */ - -#include "config.h" - -#include - -#include "vcc_compile.h" - -/*--------------------------------------------------------------------*/ - -struct proccall { - VTAILQ_ENTRY(proccall) list; - struct proc *p; - struct token *t; -}; - -struct procuse { - VTAILQ_ENTRY(procuse) list; - const struct token *t; - unsigned mask; - const char *use; -}; - -struct proc { - VTAILQ_HEAD(,proccall) calls; - VTAILQ_HEAD(,procuse) uses; - struct token *name; - unsigned ret_bitmap; - unsigned exists; - unsigned called; - unsigned active; - struct token *return_tok[VCL_RET_MAX]; -}; - -/*-------------------------------------------------------------------- - * Keep track of definitions and references - */ - -void -vcc_AddRef(struct vcc *tl, const struct token *t, enum symkind kind) -{ - struct symbol *sym; - - sym = VCC_GetSymbolTok(tl, t, kind); - AN(sym); - sym->nref++; -} - -int -vcc_AddDef(struct vcc *tl, const struct token *t, enum symkind kind) -{ - struct symbol *sym; - - sym = VCC_GetSymbolTok(tl, t, kind); - AN(sym); - sym->ndef++; - return (sym->ndef); -} - -/*--------------------------------------------------------------------*/ - -static void -vcc_checkref(struct vcc *tl, const struct symbol *sym) -{ - - if (sym->ndef == 0 && sym->nref != 0) { - VSB_printf(tl->sb, "Undefined %s %.*s, first reference:\n", - VCC_SymKind(tl, sym), PF(sym->def_b)); - vcc_ErrWhere(tl, sym->def_b); - } else if (sym->ndef != 0 && sym->nref == 0) { - VSB_printf(tl->sb, "Unused %s %.*s, defined:\n", - VCC_SymKind(tl, sym), PF(sym->def_b)); - vcc_ErrWhere(tl, sym->def_b); - if (!tl->err_unref) { - VSB_printf(tl->sb, "(That was just a warning)\n"); - tl->err = 0; - } - } -} - -int -vcc_CheckReferences(struct vcc *tl) -{ - - VCC_WalkSymbols(tl, vcc_checkref, SYM_NONE); - return (tl->err); -} - -/*-------------------------------------------------------------------- - * Returns checks - */ - -static struct proc * -vcc_findproc(struct vcc *tl, struct token *t) -{ - struct symbol *sym; - struct proc *p; - - - sym = VCC_GetSymbolTok(tl, t, SYM_SUB); - AN(sym); - if (sym->proc != NULL) - return (sym->proc); - - p = TlAlloc(tl, sizeof *p); - assert(p != NULL); - VTAILQ_INIT(&p->calls); - VTAILQ_INIT(&p->uses); - p->name = t; - sym->proc = p; - return (p); -} - -struct proc * -vcc_AddProc(struct vcc *tl, struct token *t) -{ - struct proc *p; - - p = vcc_findproc(tl, t); - p->name = t; /* make sure the name matches the definition */ - p->exists++; - return (p); -} - -void -vcc_AddUses(struct vcc *tl, const struct token *t, unsigned mask, - const char *use) -{ - struct procuse *pu; - - if (tl->curproc == NULL) /* backend */ - return; - pu = TlAlloc(tl, sizeof *pu); - assert(pu != NULL); - pu->t = t; - pu->mask = mask; - pu->use = use; - VTAILQ_INSERT_TAIL(&tl->curproc->uses, pu, list); -} - -void -vcc_AddCall(struct vcc *tl, struct token *t) -{ - struct proccall *pc; - struct proc *p; - - p = vcc_findproc(tl, t); - pc = TlAlloc(tl, sizeof *pc); - assert(pc != NULL); - pc->p = p; - pc->t = t; - VTAILQ_INSERT_TAIL(&tl->curproc->calls, pc, list); -} - -void -vcc_ProcAction(struct proc *p, unsigned returns, struct token *t) -{ - - assert(returns < VCL_RET_MAX); - p->ret_bitmap |= (1U << returns); - /* Record the first instance of this return */ - if (p->return_tok[returns] == NULL) - p->return_tok[returns] = t; -} - -static int -vcc_CheckActionRecurse(struct vcc *tl, struct proc *p, unsigned bitmap) -{ - unsigned u; - struct proccall *pc; - - if (!p->exists) { - VSB_printf(tl->sb, "Function %.*s does not exist\n", - PF(p->name)); - return (1); - } - if (p->active) { - VSB_printf(tl->sb, "Function recurses on\n"); - vcc_ErrWhere(tl, p->name); - return (1); - } - u = p->ret_bitmap & ~bitmap; - if (u) { - -#define VCL_RET_MAC(l, U, B) \ - if (u & (1 << (VCL_RET_##U))) { \ - VSB_printf(tl->sb, "Invalid return \"" #l "\"\n");\ - vcc_ErrWhere(tl, p->return_tok[VCL_RET_##U]); \ - } -#include "tbl/vcl_returns.h" -#undef VCL_RET_MAC - - VSB_printf(tl->sb, "\n...in subroutine \"%.*s\"\n", - PF(p->name)); - vcc_ErrWhere(tl, p->name); - return (1); - } - p->active = 1; - VTAILQ_FOREACH(pc, &p->calls, list) { - if (vcc_CheckActionRecurse(tl, pc->p, bitmap)) { - VSB_printf(tl->sb, "\n...called from \"%.*s\"\n", - PF(p->name)); - vcc_ErrWhere(tl, pc->t); - return (1); - } - } - p->active = 0; - p->called++; - return (0); -} - -/*--------------------------------------------------------------------*/ - -static void -vcc_checkaction1(struct vcc *tl, const struct symbol *sym) -{ - struct proc *p; - struct method *m; - int i; - - p = sym->proc; - AN(p); - i = IsMethod(p->name); - if (i < 0) - return; - m = method_tab + i; - if (vcc_CheckActionRecurse(tl, p, m->ret_bitmap)) { - VSB_printf(tl->sb, - "\n...which is the \"%s\" method\n", m->name); - VSB_printf(tl->sb, "Legal returns are:"); -#define VCL_RET_MAC(l, U, B) \ - if (m->ret_bitmap & ((1 << VCL_RET_##U))) \ - VSB_printf(tl->sb, " \"%s\"", #l); - -#include "tbl/vcl_returns.h" -#undef VCL_RET_MAC - VSB_printf(tl->sb, "\n"); - tl->err = 1; - } - -} - -static void -vcc_checkaction2(struct vcc *tl, const struct symbol *sym) -{ - struct proc *p; - - p = sym->proc; - AN(p); - - if (p->called) - return; - VSB_printf(tl->sb, "Function unused\n"); - vcc_ErrWhere(tl, p->name); - if (!tl->err_unref) { - VSB_printf(tl->sb, "(That was just a warning)\n"); - tl->err = 0; - } -} - -int -vcc_CheckAction(struct vcc *tl) -{ - - VCC_WalkSymbols(tl, vcc_checkaction1, SYM_SUB); - if (tl->err) - return (tl->err); - VCC_WalkSymbols(tl, vcc_checkaction2, SYM_SUB); - return (tl->err); -} - -/*--------------------------------------------------------------------*/ - -static struct procuse * -vcc_FindIllegalUse(const struct proc *p, const struct method *m) -{ - struct procuse *pu; - - VTAILQ_FOREACH(pu, &p->uses, list) - if (!(pu->mask & m->bitval)) - return (pu); - return (NULL); -} - -static int -vcc_CheckUseRecurse(struct vcc *tl, const struct proc *p, - struct method *m) -{ - struct proccall *pc; - struct procuse *pu; - - pu = vcc_FindIllegalUse(p, m); - if (pu != NULL) { - VSB_printf(tl->sb, - "'%.*s': %s from method '%.*s'.\n", - PF(pu->t), pu->use, PF(p->name)); - vcc_ErrWhere(tl, pu->t); - VSB_printf(tl->sb, "\n...in subroutine \"%.*s\"\n", - PF(p->name)); - vcc_ErrWhere(tl, p->name); - return (1); - } - VTAILQ_FOREACH(pc, &p->calls, list) { - if (vcc_CheckUseRecurse(tl, pc->p, m)) { - VSB_printf(tl->sb, "\n...called from \"%.*s\"\n", - PF(p->name)); - vcc_ErrWhere(tl, pc->t); - return (1); - } - } - return (0); -} - -static void -vcc_checkuses(struct vcc *tl, const struct symbol *sym) -{ - struct proc *p; - struct method *m; - struct procuse *pu; - int i; - - p = sym->proc; - AN(p); - - i = IsMethod(p->name); - if (i < 0) - return; - m = method_tab + i; - pu = vcc_FindIllegalUse(p, m); - if (pu != NULL) { - VSB_printf(tl->sb, - "'%.*s': %s in method '%.*s'.", - PF(pu->t), pu->use, PF(p->name)); - VSB_cat(tl->sb, "\nAt: "); - vcc_ErrWhere(tl, pu->t); - return; - } - if (vcc_CheckUseRecurse(tl, p, m)) { - VSB_printf(tl->sb, - "\n...which is the \"%s\" method\n", m->name); - return; - } -} - -int -vcc_CheckUses(struct vcc *tl) -{ - - VCC_WalkSymbols(tl, vcc_checkuses, SYM_SUB); - return (tl->err); -} diff --git a/lib/libvcl/vmodtool.py b/lib/libvcl/vmodtool.py deleted file mode 100755 index 2b6db42..0000000 --- a/lib/libvcl/vmodtool.py +++ /dev/null @@ -1,553 +0,0 @@ -#!/usr/bin/env python -#- -# Copyright (c) 2010-2013 Varnish Software AS -# All rights reserved. -# -# Author: Poul-Henning Kamp -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# Read the vmod.spec file and produce the vmod.h and vmod.c files. -# -# vmod.h contains the prototypes for the published functions, the module -# C-code should include this file to ensure type-consistency. -# -# vmod.c contains the symbols which VCC and varnishd will use to access -# the module: A structure of properly typed function pointers, the -# size of this structure in bytes, and the definition of the structure -# as a string, suitable for inclusion in the C-source of the compile VCL -# program. - -import sys -import re - -if len(sys.argv) == 2: - specfile = sys.argv[1] -else: - specfile = "vmod.vcc" - -ctypes = { - 'BACKEND': "VCL_BACKEND", - 'BOOL': "VCL_BOOL", - 'DURATION': "VCL_DURATION", - 'ENUM': "VCL_ENUM", - 'HEADER': "const struct gethdr_s *", - 'INT': "VCL_INT", - 'IP': "VCL_IP", - 'PRIV_CALL': "struct vmod_priv *", - 'PRIV_VCL': "struct vmod_priv *", - 'REAL': "VCL_REAL", - 'STRING': "VCL_STRING", - 'STRING_LIST': "const char *, ...", - 'TIME': "VCL_TIME", - 'VOID': "VCL_VOID", -} - -####################################################################### - -def file_header(fo): - fo.write("""/* - * NB: This file is machine generated, DO NOT EDIT! - * - * Edit vmod.vcc and run vmod.py instead - */ - -""") - -####################################################################### - -def is_c_name(s): - return None != re.match("^[a-z][a-z0-9_]*$", s) - -####################################################################### - -class token(object): - def __init__(self, ln, ch, str): - self.ln = ln - self.ch = ch - self.str = str - - def __repr__(self): - return "<@%d \"%s\">" % (self.ln, self.str) - -####################################################################### - -class vmod(object): - def __init__(self, nam): - if not is_c_name(nam): - raise Exception("Module name '%s' is illegal" % nam) - self.nam = nam - self.init = None - self.funcs = list() - self.objs = list() - - def set_init(self, nam): - if self.init != None: - raise Exception("Module %s already has Init" % self.nam) - if not is_c_name(nam): - raise Exception("Init name '%s' is illegal" % nam) - self.init = nam - - def add_func(self, fn): - self.funcs.append(fn) - - def add_obj(self, obj): - self.objs.append(obj) - obj.set_modnam(self.nam) - - def c_proto(self, fo): - for o in self.objs: - o.c_proto(fo) - fo.write("\n") - for f in self.funcs: - f.c_proto(fo) - if self.init != None: - fo.write("\n") - fo.write("int " + self.init) - fo.write( - "(struct vmod_priv *, const struct VCL_conf *);\n") - #fo.write("\n") - #fo.write("extern const void * const Vmod_" + self.nam + "_Id;\n") - - def c_typedefs_(self): - l = list() - for o in self.objs: - for t in o.c_typedefs(self.nam): - l.append(t) - l.append("") - l.append("/* Functions */") - for f in self.funcs: - l.append(f.c_typedef(self.nam)) - l.append("") - return l - - def c_typedefs(self, fo): - for i in self.c_typedefs_(): - fo.write(i + "\n") - - def c_vmod(self, fo): - fo.write('const char Vmod_' + self.nam + '_Name[] =') - fo.write(' \"' + self.nam + '";\n') - fo.write("\n") - - cs = self.c_struct() - fo.write("const " + cs + ' Vmod_' + self.nam + '_Func = ') - fo.write(self.c_initializer()) - fo.write("\n") - - fo.write("\n") - fo.write("const int Vmod_" + self.nam + '_Len =') - fo.write(" sizeof(Vmod_" + self.nam + "_Func);\n") - fo.write("\n") - - fo.write("const char Vmod_" + self.nam + "_Proto[] =\n") - for t in self.c_typedefs_(): - fo.write('\t"' + t + '\\n"\n') - fo.write('\t"\\n"\n') - for i in (cs + " Vmod_" + self.nam + '_Func;').split("\n"): - fo.write('\n\t"' + i + '\\n"') - fo.write(";\n\n") - - fo.write(self.c_strspec()) - - fo.write("\n") - fo.write('const char Vmod_' + self.nam + '_ABI[] =') - fo.write(' VMOD_ABI_Version;\n') - #fo.write("\n") - #fo.write('const void * const Vmod_' + self.nam + '_Id =') - #fo.write(' &Vmod_' + self.nam + '_Id;\n') - - def c_initializer(self): - s = '{\n' - for o in self.objs: - s += o.c_initializer() - - s += "\n\t/* Functions */\n" - for f in self.funcs: - s += f.c_initializer() - - s += "\n\t/* Init/Fini */\n" - if self.init != None: - s += "\t" + self.init + ",\n" - s += "};" - - return s - - def c_struct(self): - s = 'struct Vmod_' + self.nam + '_Func {\n' - for o in self.objs: - s += o.c_struct(self.nam) - - s += "\n\t/* Functions */\n" - for f in self.funcs: - s += f.c_struct(self.nam) - - s += "\n\t/* Init/Fini */\n" - if self.init != None: - s += "\tvmod_init_f\t*_init;\n" - s += '}' - return s - - def c_strspec(self): - s = "const char * const Vmod_" + self.nam + "_Spec[] = {\n" - - for o in self.objs: - s += o.c_strspec(self.nam) - - s += "\n\t/* Functions */\n" - for f in self.funcs: - s += '\t"' + f.c_strspec(self.nam) + '",\n' - - s += "\n\t/* Init/Fini */\n" - if self.init != None: - s += '\t"INIT\\0Vmod_' + self.nam + '_Func._init",\n' - - s += "\t0\n" - s += "};\n" - return s - -####################################################################### - -class func(object): - def __init__(self, nam, retval, al): - #if not is_c_name(nam): - # raise Exception("Func name '%s' is illegal" % nam) - if retval not in ctypes: - raise Exception( - "Return type '%s' not a valid type" % retval) - self.nam = nam - self.cnam = nam.replace(".", "_") - self.al = al - self.retval = retval - self.pfx = None - - def __repr__(self): - return "" % (self.retval, self.nam) - - def set_pfx(self, s): - self.pfx = s - - def c_proto(self, fo, fini=False): - fo.write(ctypes[self.retval]) - fo.write(" vmod_" + self.cnam + "(") - p = "" - if not fini: - fo.write("const struct vrt_ctx *") - p = ", " - if self.pfx != None: - fo.write(p + self.pfx) - p = ", " - for a in self.al: - fo.write(p + ctypes[a.typ]) - p = ", " - if a.nam != None: - fo.write(" " + a.nam) - fo.write(");\n") - - def c_typedef(self, modname, fini=False): - s = "typedef " - s += ctypes[self.retval] - s += " td_" + modname + "_" + self.cnam + "(" - p = "" - if not fini: - s += "const struct vrt_ctx *" - p = ", " - if self.pfx != None: - s += p + self.pfx - p = ", " - for a in self.al: - s += p + ctypes[a.typ] - p = ", " - s += ");" - return s - - def c_struct(self, modname): - s = '\ttd_' + modname + "_" + self.cnam - while len(s.expandtabs()) < 40: - s += "\t" - s += "*" + self.cnam + ";\n" - return s - - def c_initializer(self): - return "\tvmod_" + self.cnam + ",\n" - - def c_strspec(self, modnam): - s = modnam + "." + self.nam - s += "\\0" - s += "Vmod_" + modnam + "_Func." + self.cnam + "\\0" - s += self.retval + "\\0" - for a in self.al: - s += a.c_strspec() - return s - -####################################################################### - -class obj(object): - def __init__(self, nam): - self.nam = nam - self.init = None - self.fini = None - self.methods = list() - - def set_modnam(self, modnam): - self.st = "struct vmod_" + modnam + "_" + self.nam - self.init.set_pfx(self.st + " **, const char *") - self.fini.set_pfx(self.st + " **") - for m in self.methods: - m.set_pfx(self.st + " *") - - def set_init(self, f): - self.init = f - self.fini = func(f.nam, "VOID", []) - self.init.cnam += "__init" - self.fini.cnam += "__fini" - - def add_method(self, m): - self.methods.append(m) - - def c_typedefs(self, modnam): - l = list() - l.append("/* Object " + self.nam + " */") - l.append(self.st + ";") - l.append(self.init.c_typedef(modnam) + "") - l.append(self.fini.c_typedef(modnam, fini=True) + "") - for m in self.methods: - l.append(m.c_typedef(modnam) + "") - return l - - def c_proto(self, fo): - fo.write(self.st + ";\n") - self.init.c_proto(fo) - self.fini.c_proto(fo, fini = True) - for m in self.methods: - m.c_proto(fo) - - def c_struct(self, modnam): - s = "\t/* Object " + self.nam + " */\n" - s += self.init.c_struct(modnam) - s += self.fini.c_struct(modnam) - for m in self.methods: - s += m.c_struct(modnam) - return s - - def c_initializer(self): - s = "\t/* Object " + self.nam + " */\n" - s += self.init.c_initializer() - s += self.fini.c_initializer() - for m in self.methods: - s += m.c_initializer() - return s - - def c_strspec(self, modnam): - s = "\t/* Object " + self.nam + " */\n" - s += '\t"OBJ\\0"\n' - s += '\t\t"' + self.init.c_strspec(modnam) + '\\0"\n' - s += '\t\t"' + self.st + '\\0"\n' - s += '\t\t"' + self.fini.c_strspec(modnam) + '\\0"\n' - for m in self.methods: - s += '\t\t"' + m.c_strspec(modnam) + '\\0"\n' - s += '\t\t"\\0",\n' - return s - -####################################################################### - -class arg(object): - def __init__(self, typ, nam = None, det = None): - self.nam = nam - self.typ = typ - self.det = det - - def __repr__(self): - return "" % (self.nam, self.typ, str(self.det)) - - def c_strspec(self): - if self.det == None: - return self.typ + "\\0" - else: - return self.det - return "??" - -####################################################################### - -f = open(specfile, "r") -tl = list() -lines = list() -ln = 0 -for l in f: - ln += 1 - lines.append(l) - if l == "": - continue - l = re.sub("[ \t]*#.*$", "", l) - l = re.sub("[ \t]*\n", "", l) - l = re.sub("([(){},])", r' \1 ', l) - if l == "": - continue - for j in l.split(): - tl.append(token(ln, 0, j)) -f.close() - -####################################################################### -# -# -def parse_enum2(tl): - t = tl.pop(0) - if t.str != "{": - raise Exception("expected \"{\"") - s = "ENUM\\0" - while True: - t = tl.pop(0) - if t.str == "}": - break - s += t.str + "\\0" - if tl[0].str == ",": - tl.pop(0) - elif tl[0].str != "}": - raise Exception("Expceted \"}\" or \",\"") - s += "\\0" - return arg("ENUM", det=s) - -####################################################################### -# -# - -def parse_func(tl, rt_type = None, obj=None): - al = list() - if rt_type == None: - t = tl.pop(0) - rt_type = t.str - if rt_type not in ctypes: - raise Exception( - "Return type '%s' not a valid type" % rt_type) - - t = tl.pop(0) - fname = t.str - if obj != None and fname[0] == "." and is_c_name(fname[1:]): - fname = obj + fname - elif not is_c_name(fname): - raise Exception("Function name '%s' is illegal" % fname) - - t = tl.pop(0) - if t.str != "(": - raise Exception("Expected \"(\" got \"%s\"", t.str) - - while True: - t = tl.pop(0) - if t.str == ")": - break - if t.str == "ENUM": - al.append(parse_enum2(tl)) - elif t.str in ctypes: - al.append(arg(t.str)) - else: - raise Exception("ARG? %s" % t.str) - if is_c_name(tl[0].str): - al[-1].nam = tl[0].str - t = tl.pop(0) - if tl[0].str == ",": - tl.pop(0) - elif tl[0].str != ")": - raise Exception("Expceted \")\" or \",\"") - if t.str != ")": - raise Exception("End Of Input looking for ')'") - f = func(fname, rt_type, al) - return f - -####################################################################### -# -# - -def parse_obj(tl): - o = obj(tl[0].str) - f = parse_func(tl, "VOID") - o.set_init(f) - t = tl.pop(0) - assert t.str == "{" - while True: - t = tl.pop(0) - if t.str == "}": - break - assert t.str == "Method" - f = parse_func(tl, obj=o.nam) - o.add_method(f) - return o - -####################################################################### -# The first thing in the file must be the Module declaration -# - -t = tl.pop(0) -if t.str != "Module": - raise Exception("\"Module\" must be first in file") -t = tl.pop(0) -vmod = vmod(t.str) - -####################################################################### -# Parse the rest of the file -# - -while len(tl) > 0: - t = tl.pop(0) - - if t.str == "Init": - t = tl.pop(0) - vmod.set_init(t.str) - elif t.str == "Function": - f = parse_func(tl) - vmod.add_func(f) - elif t.str == "Object": - o = parse_obj(tl) - vmod.add_obj(o) - else: - raise Exception("Expected \"Init\", \"Fini\" or \"Function\"") - -####################################################################### -# Parsing done, now process -# - -fc = open("vcc_if.c", "w") -fh = open("vcc_if.h", "w") - -file_header(fc) -file_header(fh) - -fh.write('struct vrt_ctx;\n') -fh.write('struct VCL_conf;\n') -fh.write('struct vmod_priv;\n') -fh.write("\n"); - -vmod.c_proto(fh) - -fc.write("""#include "config.h" - -#include "vrt.h" -#include "vcc_if.h" -#include "vmod_abi.h" - - -""") - -vmod.c_typedefs(fc) -vmod.c_vmod(fc) - -fc.close() -fh.close() diff --git a/lib/libvmod_debug/Makefile.am b/lib/libvmod_debug/Makefile.am index 7e2c849..f73720c 100644 --- a/lib/libvmod_debug/Makefile.am +++ b/lib/libvmod_debug/Makefile.am @@ -8,7 +8,7 @@ AM_CPPFLAGS = \ vmoddir = $(pkglibdir)/vmods vmod_srcdir = $(top_srcdir)/lib/libvmod_debug -vmodtool = $(top_srcdir)/lib/libvcl/vmodtool.py +vmodtool = $(top_srcdir)/lib/libvcc/vmodtool.py noinst_LTLIBRARIES = libvmod_debug.la libvmod_debug_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version -shared -rpath /nowhere diff --git a/lib/libvmod_directors/Makefile.am b/lib/libvmod_directors/Makefile.am index e49a285..7e2e2f3 100644 --- a/lib/libvmod_directors/Makefile.am +++ b/lib/libvmod_directors/Makefile.am @@ -8,7 +8,7 @@ AM_CPPFLAGS = \ vmoddir = $(pkglibdir)/vmods vmod_srcdir = $(top_srcdir)/lib/libvmod_directors -vmodtool = $(top_srcdir)/lib/libvcl/vmodtool.py +vmodtool = $(top_srcdir)/lib/libvcc/vmodtool.py noinst_LTLIBRARIES = libvmod_directors.la libvmod_directors_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version -shared -rpath /nowhere diff --git a/lib/libvmod_std/Makefile.am b/lib/libvmod_std/Makefile.am index acc0842..cd55e5b 100644 --- a/lib/libvmod_std/Makefile.am +++ b/lib/libvmod_std/Makefile.am @@ -11,7 +11,7 @@ dist_man_MANS = vmod_std.3 vmoddir = $(pkglibdir)/vmods vmod_srcdir = $(top_srcdir)/lib/libvmod_std -vmodtool = $(top_srcdir)/lib/libvcl/vmodtool.py +vmodtool = $(top_srcdir)/lib/libvcc/vmodtool.py vmod_LTLIBRARIES = libvmod_std.la libvmod_std_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version -shared diff --git a/redhat/varnish.spec b/redhat/varnish.spec index ea0fc24..df56f62 100644 --- a/redhat/varnish.spec +++ b/redhat/varnish.spec @@ -150,7 +150,7 @@ rm -rf doc/sphinx/\=build %endif %endif -make check LD_LIBRARY_PATH="../../lib/libvarnish/.libs:../../lib/libvarnishcompat/.libs:../../lib/libvarnishapi/.libs:../../lib/libvcl/.libs:../../lib/libvgz/.libs" +make check LD_LIBRARY_PATH="../../lib/libvarnish/.libs:../../lib/libvarnishcompat/.libs:../../lib/libvarnishapi/.libs:../../lib/libvcc/.libs:../../lib/libvgz/.libs" %install rm -rf %{buildroot} @@ -247,7 +247,7 @@ rm -rf %{buildroot} #%{_libdir}/libvarnish.a #%{_libdir}/libvarnishapi.a #%{_libdir}/libvarnishcompat.a -#%{_libdir}/libvcl.a +#%{_libdir}/libvcc.a #%doc LICENSE %pre From phk at varnish-cache.org Tue Sep 17 12:23:34 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 17 Sep 2013 14:23:34 +0200 Subject: [master] 72db3c4 Try to make Jenkins happier Message-ID: commit 72db3c42c15bd5b6cdda8db81586bbb3acc3d2ba Author: Poul-Henning Kamp Date: Tue Sep 17 12:23:25 2013 +0000 Try to make Jenkins happier diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index cb59bad..846a945 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -455,6 +455,7 @@ static enum fetch_step vbf_stp_done(void) { WRONG("Just plain wrong"); + return (F_STP_DONE); } /*-------------------------------------------------------------------- From phk at varnish-cache.org Tue Sep 17 12:58:40 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 17 Sep 2013 14:58:40 +0200 Subject: [master] 4b7fc93 Add a necessay cast Message-ID: commit 4b7fc939cdde093904e983604c54f14c4961a1d0 Author: Poul-Henning Kamp Date: Tue Sep 17 12:58:29 2013 +0000 Add a necessay cast diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c index 846a945..df311be 100644 --- a/bin/varnishd/cache/cache_fetch.c +++ b/bin/varnishd/cache/cache_fetch.c @@ -218,7 +218,7 @@ vbf_stp_fetchhdr(struct worker *wrk, struct busyobj *bo) if (bo->ims_obj != NULL && bo->beresp->status == 304) { bo->beresp->status = 200; http_PrintfHeader(bo->beresp, "Content-Length: %jd", - bo->ims_obj->len); + (intmax_t)bo->ims_obj->len); do_ims = 1; } else do_ims = 0; From phk at varnish-cache.org Tue Sep 17 13:44:51 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 17 Sep 2013 15:44:51 +0200 Subject: [master] ff23413 Eat more space now that struct obj got smaller Message-ID: commit ff23413d40ad10838246a785a130b215c9f270c3 Author: Poul-Henning Kamp Date: Tue Sep 17 13:44:40 2013 +0000 Eat more space now that struct obj got smaller diff --git a/bin/varnishtest/tests/r01284.vtc b/bin/varnishtest/tests/r01284.vtc index 7035536..b187505 100644 --- a/bin/varnishtest/tests/r01284.vtc +++ b/bin/varnishtest/tests/r01284.vtc @@ -6,7 +6,7 @@ server s1 { txresp -bodylen 1048070 rxreq expect req.url == "/obj2" - txresp -hdr "Long: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -hdr "Long2: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + txresp -hdr "Long: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -hdr "Long2: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -hdr "Long3: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" } -start varnish v1 -arg "-p nuke_limit=0" -storage "-sTransient=malloc,1m" -vcl+backend { From phk at varnish-cache.org Tue Sep 17 14:40:05 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 17 Sep 2013 16:40:05 +0200 Subject: [master] 19c304a More tweaking of test-cases for Jenkins Message-ID: commit 19c304ac163cb92b750a074a3efd493d225068cf Author: Poul-Henning Kamp Date: Tue Sep 17 14:39:51 2013 +0000 More tweaking of test-cases for Jenkins diff --git a/bin/varnishtest/tests/c00058.vtc b/bin/varnishtest/tests/c00058.vtc index f39e3e3..9811b79 100644 --- a/bin/varnishtest/tests/c00058.vtc +++ b/bin/varnishtest/tests/c00058.vtc @@ -10,7 +10,7 @@ server s1 { varnish v1 -vcl+backend { sub vcl_backend_response { - set beresp.ttl = 0.1s; + set beresp.ttl = 0.5s; set beresp.grace = 10s; } } -start @@ -30,6 +30,7 @@ client c1 { # But bg fetch was kicked off sema r2 sync 2 + delay .2 # And now we get the new object txreq diff --git a/bin/varnishtest/tests/r01284.vtc b/bin/varnishtest/tests/r01284.vtc index b187505..aedd1df 100644 --- a/bin/varnishtest/tests/r01284.vtc +++ b/bin/varnishtest/tests/r01284.vtc @@ -11,6 +11,7 @@ server s1 { varnish v1 -arg "-p nuke_limit=0" -storage "-sTransient=malloc,1m" -vcl+backend { sub vcl_backend_response { + set beresp.do_stream = false; set beresp.storage = "Transient"; } } -start From phk at varnish-cache.org Tue Sep 17 15:20:37 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 17 Sep 2013 17:20:37 +0200 Subject: [master] ee58c33 More test-case tweaking for Jenkins. This time based on actually understanding what the test-cases do. Message-ID: commit ee58c33a7cacd1a9c7495e005991238f83d78e39 Author: Poul-Henning Kamp Date: Tue Sep 17 15:20:05 2013 +0000 More test-case tweaking for Jenkins. This time based on actually understanding what the test-cases do. diff --git a/bin/varnishtest/tests/r01283.vtc b/bin/varnishtest/tests/r01283.vtc index 76fa434..c81da5a 100644 --- a/bin/varnishtest/tests/r01283.vtc +++ b/bin/varnishtest/tests/r01283.vtc @@ -2,7 +2,7 @@ varnishtest "#1283 - Test failure to allocate object for error (transient full)" server s1 { rxreq - txresp -bodylen 1048070 + txresp -bodylen 1048140 } -start varnish v1 -arg "-p nuke_limit=0" -storage "-sTransient=malloc,1m" -vcl+backend { @@ -12,6 +12,7 @@ varnish v1 -arg "-p nuke_limit=0" -storage "-sTransient=malloc,1m" -vcl+backend } } sub vcl_backend_response { + set beresp.do_stream = false; set beresp.storage = "Transient"; } } -start diff --git a/bin/varnishtest/tests/r01284.vtc b/bin/varnishtest/tests/r01284.vtc index aedd1df..74f1306 100644 --- a/bin/varnishtest/tests/r01284.vtc +++ b/bin/varnishtest/tests/r01284.vtc @@ -3,10 +3,10 @@ varnishtest "#1284 - Test resource cleanup after STV_NewObject fail in fetch" server s1 { rxreq expect req.url == "/obj1" - txresp -bodylen 1048070 + txresp -bodylen 1048140 rxreq expect req.url == "/obj2" - txresp -hdr "Long: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -hdr "Long2: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -hdr "Long3: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + txresp -hdr "Long: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -hdr "Long2: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" } -start varnish v1 -arg "-p nuke_limit=0" -storage "-sTransient=malloc,1m" -vcl+backend { From phk at varnish-cache.org Tue Sep 17 16:25:48 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 17 Sep 2013 18:25:48 +0200 Subject: [master] 7196e8a More test-case tuning for Jenkins Message-ID: commit 7196e8a8525481a00caa0269475d8223f4f56b12 Author: Poul-Henning Kamp Date: Tue Sep 17 16:25:39 2013 +0000 More test-case tuning for Jenkins diff --git a/bin/varnishtest/tests/r01140.vtc b/bin/varnishtest/tests/r01140.vtc index 4bd0b3b..f18de6c 100644 --- a/bin/varnishtest/tests/r01140.vtc +++ b/bin/varnishtest/tests/r01140.vtc @@ -4,7 +4,7 @@ server s1 { # This response should almost completely fill the storage rxreq expect req.url == /url1 - txresp -bodylen 1048050 + txresp -bodylen 1048100 # The next one should not fit in the storage, ending up in transient # with zero ttl (=shortlived) @@ -19,19 +19,33 @@ server s1 { } -start varnish v1 -arg "-p expiry_sleep=0.01 -p nuke_limit=0 -p shortlived=0" \ - -storage "-smalloc,1m" -vcl+backend { } -start + -storage "-smalloc,1m" -vcl+backend { + sub vcl_backend_response { + set beresp.do_stream = false; + } +} -start client c1 { txreq -url /url1 rxresp expect resp.status == 200 - expect resp.bodylen == 1048050 + expect resp.bodylen == 1048100 +} -run + +delay .1 + +varnish v1 -expect SMA.s0.g_space < 1000 +client c1 { txreq -url /url2 rxresp expect resp.status == 200 expect resp.bodylen == 1024 +} -run +delay .1 + +client c1 { txreq -url /url2 rxresp expect resp.status == 200 From phk at varnish-cache.org Tue Sep 17 17:09:26 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 17 Sep 2013 19:09:26 +0200 Subject: [master] 8053635 Tune another test-case Message-ID: commit 8053635e8f901bfb3b8812dbc73fa9c266472cb0 Author: Poul-Henning Kamp Date: Tue Sep 17 17:09:16 2013 +0000 Tune another test-case diff --git a/bin/varnishtest/tests/c00045.vtc b/bin/varnishtest/tests/c00045.vtc index b150770..73d87a6 100644 --- a/bin/varnishtest/tests/c00045.vtc +++ b/bin/varnishtest/tests/c00045.vtc @@ -2,15 +2,16 @@ varnishtest "Object/LRU/Stevedores with hinting" server s1 { rxreq - txresp -bodylen 1048092 + txresp -bodylen 1048172 rxreq - txresp -bodylen 1048093 + txresp -bodylen 1048173 rxreq - txresp -bodylen 1048094 + txresp -bodylen 1048174 } -start varnish v1 -storage "-smalloc,1m -smalloc,1m, -smalloc,1m" -vcl+backend { sub vcl_backend_response { + set beresp.do_stream = false; set beresp.storage = "s0"; } } -start @@ -20,7 +21,7 @@ client c1 { txreq -url /foo rxresp expect resp.status == 200 - expect resp.bodylen == 1048092 + expect resp.bodylen == 1048172 } -run varnish v1 -expect SMA.Transient.g_bytes == 0 @@ -35,7 +36,7 @@ client c1 { txreq -url /bar rxresp expect resp.status == 200 - expect resp.bodylen == 1048093 + expect resp.bodylen == 1048173 } -run varnish v1 -expect n_lru_nuked == 1 @@ -51,7 +52,7 @@ client c1 { txreq -url /foo rxresp expect resp.status == 200 - expect resp.bodylen == 1048094 + expect resp.bodylen == 1048174 } -run varnish v1 -expect n_lru_nuked == 2 From phk at varnish-cache.org Tue Sep 17 17:59:05 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Tue, 17 Sep 2013 19:59:05 +0200 Subject: [master] f1e52e7 More test-case finetuning. Message-ID: commit f1e52e7c973706444738e2e201889babbc0c4558 Author: Poul-Henning Kamp Date: Tue Sep 17 17:58:48 2013 +0000 More test-case finetuning. I'm never going to change the size of struct obj again... diff --git a/bin/varnishtest/tests/c00044.vtc b/bin/varnishtest/tests/c00044.vtc index d75ecbb..2aac160 100644 --- a/bin/varnishtest/tests/c00044.vtc +++ b/bin/varnishtest/tests/c00044.vtc @@ -2,21 +2,22 @@ varnishtest "Object/LRU/Stevedores" server s1 { rxreq - txresp -bodylen 1048092 + txresp -bodylen 1048182 rxreq - txresp -bodylen 1048093 + txresp -bodylen 1048183 rxreq - txresp -bodylen 1048094 + txresp -bodylen 1048184 rxreq - txresp -bodylen 1048095 + txresp -bodylen 1048185 rxreq - txresp -bodylen 1048096 + txresp -bodylen 1048186 } -start varnish v1 -storage "-smalloc,1m -smalloc,1m, -smalloc,1m" -vcl+backend { sub vcl_backend_response { + set beresp.do_stream = false; set beresp.storage = "invalid"; } } -start @@ -26,7 +27,7 @@ client c1 { txreq -url /foo rxresp expect resp.status == 200 - expect resp.bodylen == 1048092 + expect resp.bodylen == 1048182 } -run varnish v1 -expect SMA.Transient.g_bytes == 0 @@ -41,7 +42,7 @@ client c1 { txreq -url /bar rxresp expect resp.status == 200 - expect resp.bodylen == 1048093 + expect resp.bodylen == 1048183 } -run varnish v1 -expect SMA.Transient.g_bytes == 0 @@ -56,7 +57,7 @@ client c1 { txreq -url /burp rxresp expect resp.status == 200 - expect resp.bodylen == 1048094 + expect resp.bodylen == 1048184 } -run varnish v1 -expect SMA.Transient.g_bytes == 0 @@ -71,7 +72,7 @@ client c1 { txreq -url /foo1 rxresp expect resp.status == 200 - expect resp.bodylen == 1048095 + expect resp.bodylen == 1048185 } -run varnish v1 -expect n_lru_nuked == 1 @@ -80,7 +81,7 @@ client c1 { txreq -url /foo rxresp expect resp.status == 200 - expect resp.bodylen == 1048096 + expect resp.bodylen == 1048186 } -run varnish v1 -expect n_lru_nuked == 2 From phk at varnish-cache.org Wed Sep 18 06:59:24 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 18 Sep 2013 08:59:24 +0200 Subject: [master] 731d208 Slightly polish the vmod loading/unloading code. Message-ID: commit 731d20843eef23aea1f39d605a02dff18e5d0969 Author: Poul-Henning Kamp Date: Wed Sep 18 06:53:14 2013 +0000 Slightly polish the vmod loading/unloading code. dlopen/dlclose(3) is deficient in at least two ways, possibly three: 1. It assumes that if the path is the same, the file is the same. This makes it impossible to update VMODs in place by any means. 2. It doesn't map the dlopen'ed object in copy-on-write mode. This makes things explode if you try anyway, without a rename-guard. 3. It doesn't handle atexit(3) from dlopen(3)'ed code correctly on dlclose(3) This makes gcov(1) and friends explode. The fault could be said to be on their part though: atexit(3) from symlinked code is undefined. Since there is no sensible way to work around this, live with it, and rely on whatever check dlopen(3) uses for identity, rather than have our own name-comparison. diff --git a/bin/varnishd/cache/cache_vrt_vmod.c b/bin/varnishd/cache/cache_vrt_vmod.c index 84fb105..61e0bd0 100644 --- a/bin/varnishd/cache/cache_vrt_vmod.c +++ b/bin/varnishd/cache/cache_vrt_vmod.c @@ -69,24 +69,26 @@ VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm, struct vmod *v; void *x, *y, *z, *w; char buf[256]; + void *dlhdl; ASSERT_CLI(); + dlhdl = dlopen(path, RTLD_NOW | RTLD_LOCAL); + if (dlhdl == NULL) { + VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path); + VCLI_Out(cli, "dlopen() failed: %s\n", dlerror()); + VCLI_Out(cli, "Check child process permissions.\n"); + return (1); + } + VTAILQ_FOREACH(v, &vmods, list) - if (!strcmp(v->nm, nm)) // Also path, len ? + if (v->hdl == dlhdl) break; if (v == NULL) { ALLOC_OBJ(v, VMOD_MAGIC); AN(v); - v->hdl = dlopen(path, RTLD_NOW | RTLD_LOCAL); - if (v->hdl == NULL) { - VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path); - VCLI_Out(cli, "dlopen() failed: %s\n", dlerror()); - VCLI_Out(cli, "Check child process permissions.\n"); - FREE_OBJ(v); - return (1); - } + v->hdl = dlhdl; bprintf(buf, "Vmod_%s_Name", nm); x = dlsym(v->hdl, buf); @@ -158,11 +160,17 @@ VRT_Vmod_Fini(void **hdl) AN(*hdl); CAST_OBJ_NOTNULL(v, *hdl, VMOD_MAGIC); *hdl = NULL; - if (--v->ref != 0) - return; + #ifndef DONT_DLCLOSE_VMODS + /* + * atexit(3) handlers are not called during dlclose(3). We don't + * normally use them, but we do when running GCOV. This option + * enables us to do that. + */ AZ(dlclose(v->hdl)); #endif + if (--v->ref != 0) + return; free(v->nm); free(v->path); VTAILQ_REMOVE(&vmods, v, list); From phk at varnish-cache.org Wed Sep 18 09:57:21 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 18 Sep 2013 11:57:21 +0200 Subject: [master] 9ca5764 Fix issues exposed by different scheduling on OmniOS. Message-ID: commit 9ca576494840f6f2d638531b68167706133448f0 Author: Poul-Henning Kamp Date: Wed Sep 18 09:56:27 2013 +0000 Fix issues exposed by different scheduling on OmniOS. Notice the "-wait" necessary before reconfiguring server s1, this mistake is probably present in other testcases too. diff --git a/bin/varnishtest/tests/b00020.vtc b/bin/varnishtest/tests/b00020.vtc index dbe6831..3cf5e4b 100644 --- a/bin/varnishtest/tests/b00020.vtc +++ b/bin/varnishtest/tests/b00020.vtc @@ -6,7 +6,7 @@ server s1 { rxreq send "HTTP/1.1 200 Ok\r\nConnection: close\r\n\r\n" delay 1.5 - send "Baba\n" + # send "Baba\n" } -start varnish v1 -vcl+backend { @@ -25,7 +25,7 @@ client c1 { varnish v1 -expect n_object == 0 varnish v1 -expect n_objectcore == 0 -server s1 { +server s1 -wait { rxreq send "HTTP/1.1 200 Ok\r\nConnection: close\r\n\r\n" delay 0.5 From phk at varnish-cache.org Wed Sep 18 09:57:45 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 18 Sep 2013 11:57:45 +0200 Subject: [master] 3f0f848 Add a delay for EXP to act Message-ID: commit 3f0f8489ccdfddfb6e1731ffc955e215d3027ab9 Author: Poul-Henning Kamp Date: Wed Sep 18 09:57:37 2013 +0000 Add a delay for EXP to act diff --git a/bin/varnishtest/tests/b00020.vtc b/bin/varnishtest/tests/b00020.vtc index 3cf5e4b..20bc72b 100644 --- a/bin/varnishtest/tests/b00020.vtc +++ b/bin/varnishtest/tests/b00020.vtc @@ -22,6 +22,8 @@ client c1 { expect resp.status == 503 } -run +delay 1 + varnish v1 -expect n_object == 0 varnish v1 -expect n_objectcore == 0 From phk at varnish-cache.org Wed Sep 18 10:57:38 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 18 Sep 2013 12:57:38 +0200 Subject: [master] 1ca91d9 Make sure we don't progress the request while the SIGSEGV happens. Message-ID: commit 1ca91d9dc52ebdc5db42c8f322737e0af1755317 Author: Poul-Henning Kamp Date: Wed Sep 18 10:57:20 2013 +0000 Make sure we don't progress the request while the SIGSEGV happens. diff --git a/bin/varnishtest/tests/c00057.vtc b/bin/varnishtest/tests/c00057.vtc index 1db243d..5ac6cee 100644 --- a/bin/varnishtest/tests/c00057.vtc +++ b/bin/varnishtest/tests/c00057.vtc @@ -8,8 +8,9 @@ server s1 { varnish v1 -cliok "param.set sigsegv_handler on" -vcl+backend { C{ #include +#include }C - sub vcl_recv { C{ raise(SIGSEGV); }C } + sub vcl_recv { C{ raise(SIGSEGV); sleep(2); }C } } -start client c1 { From phk at varnish-cache.org Wed Sep 18 12:07:49 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Wed, 18 Sep 2013 14:07:49 +0200 Subject: [master] eaf1954 Increase connect_timeout default from 0.7 to 3.5 seconds to make room for a lost SYN or a slow test-box. Message-ID: commit eaf19545cbb4b6c861c2fe9511ecd1e9019ae11d Author: Poul-Henning Kamp Date: Wed Sep 18 12:07:17 2013 +0000 Increase connect_timeout default from 0.7 to 3.5 seconds to make room for a lost SYN or a slow test-box. diff --git a/bin/varnishd/mgt/mgt_param_tbl.c b/bin/varnishd/mgt/mgt_param_tbl.c index c4a9566..ab4094b 100644 --- a/bin/varnishd/mgt/mgt_param_tbl.c +++ b/bin/varnishd/mgt/mgt_param_tbl.c @@ -336,7 +336,7 @@ const struct parspec mgt_parspec[] = { "VCL can override this default value for each backend and " "backend request.", 0, - "0.7", "s" }, + "3.5", "s" }, { "first_byte_timeout", tweak_timeout_double, &mgt_param.first_byte_timeout,0, UINT_MAX, "Default timeout for receiving first byte from backend. " From phk at varnish-cache.org Fri Sep 20 10:49:02 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Fri, 20 Sep 2013 12:49:02 +0200 Subject: [master] 988cd77 Start working on the Users Guide Message-ID: commit 988cd77462865f25d76db1684df183125565e359 Author: Poul-Henning Kamp Date: Fri Sep 20 10:48:28 2013 +0000 Start working on the Users Guide diff --git a/doc/sphinx/users-guide/configuration.rst b/doc/sphinx/users-guide/configuration.rst deleted file mode 100644 index f49f99b..0000000 --- a/doc/sphinx/users-guide/configuration.rst +++ /dev/null @@ -1,17 +0,0 @@ -Configuration -============= - -This chapter deals with configuration of Varnish Cache. It will not -cover the actual configuration policy that's written in VCL. - -This guide assumes you're running Debian, Ubuntu, Red Hat or -Centos. If you're on any other platform you're probably used to doing -some mental translations. - -.. toctree:: - :maxdepth: 2 - - command-line - storage-backends - params - diff --git a/doc/sphinx/users-guide/index.rst b/doc/sphinx/users-guide/index.rst index a28b08f..7b909c9 100644 --- a/doc/sphinx/users-guide/index.rst +++ b/doc/sphinx/users-guide/index.rst @@ -1,22 +1,52 @@ .. _users-guide-index: %%%%%%%%%%%%%%%%%%%%%%%%%%%%% -Using Varnish - A Users Guide +The Varnish Users Guide %%%%%%%%%%%%%%%%%%%%%%%%%%%%% -This guide is intended for system administrators managing Varnish -Cache. +(The plan for ...) +The Varnish documentation consists of three main documents: -The guide is split into short chapters, each chapter explaining a -separate topic. +* :ref:`tutorial-index` explains the basics and gets you started with Varnish. + +* :ref:`users-guide-index` (this document), explains how Varnish works + and how you can use it to improve your website. + +* :ref:`reference-index` contains hard facts and is useful for + looking up specific questions. + +After :ref:`users_intro`, this Users Guide is organized in sections +along the major interfaces to Varnish as a service: + +:ref:`users_running` is about getting Varnish configured, with +respect to storage, sockets, security and how you can control and +communicate with Varnish once it is running. + +:ref:`users_vcl` is about getting Varnish to handle the +HTTP requests the way you want, what to cache, how to cache it, +modifying HTTP headers etc. etc. + +:ref:`users_report` explains how you can see and monitor what Varnish does, +from transaction level to aggregate statistics. + +:ref:`users_performance` is about tuning your website with Varnish. + +:ref:`users_trouble` is for locating and fixing trouble with Varnish. + + +Detailed Table of Contents: +--------------------------- .. toctree:: :maxdepth: 2 - configuration + intro + running vcl - operation + report + performance troubleshooting + operation .. customizing (which is a non ideal title) diff --git a/doc/sphinx/users-guide/intro.rst b/doc/sphinx/users-guide/intro.rst new file mode 100644 index 0000000..3d2fb0d --- /dev/null +++ b/doc/sphinx/users-guide/intro.rst @@ -0,0 +1,119 @@ +.. _users_intro: + +The Big Varnish Picture +======================= + +What is in this package called "Varnish", what are all the different +bits and pieces named and will you need a hex-wrench for assembly ? + +The two main parts of Varnish are the two processes in the varnishd +program. + +The first process is called "the manager", and its job is to talk +to you, the administrator, and make the things you ask for happen. + +The second process is called "the worker" or just "the child" and +this is the process which does all the actual work with your HTTP +traffic. + +When you start varnishd, you start the manager process, and once +it is done handling all the command line flags, it will start the +child process for you. + +Should the child process die, the manager will start it again for +you, automatically and right away. + +The main reason for this division of labor is security: The manager +process will typically run with "root" permissions, in order to +open TCP socket port 80, but it starts the child process with minimal +permissions, as a defensive measure. + +The manager process is interactive, it offers a CLI -- Command Line +Interface, which can be used manually, from scripts or programs. + +The CLI offers almost full control of what Varnish actually does +to your HTTP traffic, and we have gone to great lengths to ensure +that you should not need to restart the varnish processes, unless +you need to change something very fundamental. + +The CLI can be safely accessed remotely, using a simple and flexible +PSK -- Pre Shared Key, access control scheme, so it is easy to +integrate Varnish into your operations and management infrastructure +or tie it to your CMS. + +All this is covered in :ref:`users_running`. + +How the child process should deal with the HTTP requests, what to +cache, which headers to remove etc, is al specified in a small +programming language called VCL -- Varnish Configuration Language. + +The manager process will compile the VCL program and check it for +errors, but it is the child process which runs the VCL program, for +each and every HTTP request which comes in. + +Because the VCL is compiled to C code, and the C code is compiled +to machine instructions, even very complex VCL programs execute in +a a few microseconds, without impacting performance at all. + +And don't fret if you are not really a programmer, VCL is very +simple to do simpel things with:: + + sub vcl_recv { + # Remove the cookie header to enable caching + unset req.http.cookie; + } + +The CLI interface allows you to compile and load new VCL programs +at any time, and you can switch betweem the loaded VCL programs +instantly, without restarting the child process and without missing +a single HTTP request. + +VCL code can be extended using external modules, called VMODs or +even by inline C-code if you are brave, so in terms of what Varnish +can do for your HTTP traffic, there really is no limit. + +:ref:`users_vcl` describes VCL and what it can do in great detail. + +Varnish uses a piece of shared memory to report its activity and +status. + +For each HTTP request, a number of very detailed records will be +appended to the log segment in this shared memory. + +Other processes can subscribe to log-records, filter them, and +format them, for instance as NCSA style log records. + +Another segment in shared memory is used for statistics counters, +this allows real-time, down to microsecond resolution monitoring +of cache hit-rate, resource usage and specific performance indicating +metrics. + +Varnish comes with a number of tools which reports from shared +memory, varnishlog, varnishstats, varnishncsa etc, and with a API +library so you can write your own tools, should you need that. +writing + +:ref:`users_report` explains how all that work. + +Presumably the reason why you are interested in Varnish, is that +you want your website to work better. + +There are many aspects of performance tuning a website, from +relatively simple policy decisions about what to cache, to designing +a geographically diverse multilevel CDNs using ESI and automatic +failover. + +:ref:`users_performance` will take you through the possibilities +and facilities Varnish offers. + +Finally, Murphys Law must be contended with: Things will go wrong, +and more likely than not, they will do so at zero-zero-dark O'clock. + +...during a hurricane, when your phones battery is flat and your +wife had prepared a intimate evening to celebrate your aniversary. + +Yes, we've all been there, havn't we ? + +When things go wrong :ref:`users_trouble` will hopefully be of some help. + +And now, lets put som substance on this skeleton outline... diff --git a/doc/sphinx/users-guide/operation.rst b/doc/sphinx/users-guide/operation.rst index 4cc85fa..dc45e7e 100644 --- a/doc/sphinx/users-guide/operation.rst +++ b/doc/sphinx/users-guide/operation.rst @@ -1,15 +1,13 @@ -Operation -========= +Orphans +======= + +XXX: These are chapters which need to find a new home in the other sections. .. toctree:: :maxdepth: 2 - operation-logging - operation-statistics operation-cli purging - sizing-your-cache - increasing-your-hitrate compression esi vary diff --git a/doc/sphinx/users-guide/performance.rst b/doc/sphinx/users-guide/performance.rst new file mode 100644 index 0000000..c28dea0 --- /dev/null +++ b/doc/sphinx/users-guide/performance.rst @@ -0,0 +1,12 @@ +.. _users_performance: + +Varnish and Website Performance +=============================== + +This section is about tuning the performance of your Varnish server, +and about tuning the performance of your website using Varnish. + +.. toctree:: + :maxdepth: 2 + + increasing-your-hitrate diff --git a/doc/sphinx/users-guide/report.rst b/doc/sphinx/users-guide/report.rst new file mode 100644 index 0000000..5a444ab --- /dev/null +++ b/doc/sphinx/users-guide/report.rst @@ -0,0 +1,14 @@ +.. _users_report: + +Reporting and statistics +======================== + +This section is about how to find out what Varnish is doing, from +the detailed per HTTP request blow-by-blow logrecords to the global +summary statistics counters. + +.. toctree:: + :maxdepth: 2 + + operation-logging + operation-statistics diff --git a/doc/sphinx/users-guide/running.rst b/doc/sphinx/users-guide/running.rst new file mode 100644 index 0000000..d5f87d5 --- /dev/null +++ b/doc/sphinx/users-guide/running.rst @@ -0,0 +1,18 @@ +.. _users_running: + +Starting and running Varnish +============================ + +This section is about starting, running, and stopping Varnish, about +command line flags and options, communicating with the running +Varnish processes, configuring storage and sockets and, and about +securing and protecting Varnish against attacks. + +.. toctree:: + :maxdepth: 2 + + command-line + storage-backends + params + sizing-your-cache + diff --git a/doc/sphinx/users-guide/troubleshooting.rst b/doc/sphinx/users-guide/troubleshooting.rst index c399958..b6f6558 100644 --- a/doc/sphinx/users-guide/troubleshooting.rst +++ b/doc/sphinx/users-guide/troubleshooting.rst @@ -1,10 +1,12 @@ +.. _users_trouble: + Troubleshooting Varnish ======================= Sometimes Varnish misbehaves. In order for you to understand whats going on there are a couple of places you can check. varnishlog, /var/log/syslog, /var/log/messages are all places where varnish might -leave clues of whats going on. This chapter will guide you through +leave clues of whats going on. This section will guide you through basic troubleshooting in Varnish. diff --git a/doc/sphinx/users-guide/vcl.rst b/doc/sphinx/users-guide/vcl.rst index 0133dee..dc3fdc5 100644 --- a/doc/sphinx/users-guide/vcl.rst +++ b/doc/sphinx/users-guide/vcl.rst @@ -1,6 +1,11 @@ +.. _users_vcl: + VCL - Varnish Configuration Language ------------------------------------ +This section is about getting Varnish to do what you want to +your HTTP traffic, using the Varnish Configuration Language. + Varnish has a great configuration system. Most other systems use configuration directives, where you basically turn on and off lots of switches. Varnish uses a domain specific language called Varnish @@ -29,6 +34,7 @@ code commented out in default.vcl that ships with Varnish Cache. .. toctree:: :maxdepth: 1 + vcl-intro vcl-syntax vcl-built-in-subs vcl-variables From phk at varnish-cache.org Mon Sep 23 18:10:21 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 23 Sep 2013 20:10:21 +0200 Subject: [master] c79869b Add a chapter about securing the varnishd process Message-ID: commit c79869b2bb92f6981fa666ae5b56c885d4815d0a Author: Poul-Henning Kamp Date: Fri Sep 20 11:32:19 2013 +0000 Add a chapter about securing the varnishd process diff --git a/doc/sphinx/users-guide/run_security.rst b/doc/sphinx/users-guide/run_security.rst new file mode 100644 index 0000000..26a6b53 --- /dev/null +++ b/doc/sphinx/users-guide/run_security.rst @@ -0,0 +1,128 @@ +.. _run_security: + +Security first +============== + +If you are the only person involved in running Varnish, or if all +the people involved are trusted to the same degree, you can skip +this chapter. + +If parts of your web infrastructure are outsourced or otherwise +partitioned along adminitrative lines, you need to think about +security. + +Varnish provides four levels of authority, roughly related to +how and where the command comes into Varnish: + + * The command line arguments + + * The CLI interface + + * VCL programs + + * HTTP requests + +Command line arguments +---------------------- + +The top level security decisions is taken from the command line, +in order to make them invulnerable to subsequent manipulation. + +The important decisions to make are: + +#. Who should have access to the Command Line Interface ? + +#. Which parameters can the change ? + +#. Will inline-C code be allowed ? + +#. Will VMODs be restricted. + + +The most important of these is the CLI interface: Should it be +accessible only on the local machine, or should it be accessible +also from across the network ? + +No matter what you do, you should always protect the CLI with a +Pre-Shared-Key (The -S argument). + +The way -S/PSK works is really simple: You specify -S and filename, +and only somebody who knows what is in that file can access the CLI. + +They do not need to be able to read that specific file on that +specific machine, as long as they know *exactly* what is in that file. + +If the CLI should only be available on the local machine, bind the +CLI port to a loopback IP number ("-T 127.0.0.1"). + +If you want to be able to use the CLI remotely, you can do it +two ways: + +You can bind the CLI port to a reachable IP number, and connect +directly. This gives you no secrecy, the CLI commands will +go across the network as ASCII test with no encryption. + +Or you can bind the CLI port locally, and give remote users access +via a secure connection to the local machine (ssh, VPN, etc. etc.) + +It is also possible to configure varnishd for "reverse mode", where +varnishd will attempt to open a TCP connection to a specified +address, and initiate a CLI connection on it. This is meant to +make it easier to manage a cluster of varnish machines from a single +"cluster controller" process. + +Other parameters to consider are the uid/gid of the child process. + +The CLI interface +----------------- + +The CLI interface in Varnish is very powerful, if you have +access to the CLI interface, you can do almost anything to +the varnish process. + +Some restrictions can be put in place from the command line arguments, +for instance specific parameters can be made Read-Only with the -r +argument, which prevents changes to them from the CLI. + +We do not currently have a way to restrict specific CLI commands +to specific CLI connections. (One way to get such an effect is to +not "wrap" all CLI access in pre-approved scripts which use +varnishadm(1) to submit the sanitized CLI commands, and restrict a +remote user to only those scripts in sshd(8)'s configuration.) + +VCL programs +------------ + +There are two "dangerous" mechnisms available in VCL code: VMODs +and inline-C. + +Both of these mechanisms allow execution of arbitrary code and will +therefore allow a person to get shell access on the computer. +(XXX: doc which privs) + +Inline C can be disabled with the parameter "vcc_allow_inline_c", +remember to make it read-only from the commandline if you don't +trust the CLI wranglers to leave it alone. + +VMODs can be restricted to be loaded only from the path specified +using parameter 'vmod_dir' using the 'vcc_unsafe_path' parameter. +Again: remember to make the read-only. + +If you do this, we belive that the integrity of the machine +running varnishd, cannot be compromised from the VCL program, +but it will be possible to read files available to the child +process. + +HTTP requests +------------- + +We have gone to great lengths to make varnish resistant to anything +coming in throught he socket where HTTP requests are received, +but given that VCL is a programming language which lets you +decide exactly what to do about HTTP requests, you can also decide +to do stupid things to them. + +VCL offers a IP based Access-Control-List facility which allows you +to restrict certain requests, for instance PURGE, to certain IP +numbers/ranges. + diff --git a/doc/sphinx/users-guide/running.rst b/doc/sphinx/users-guide/running.rst index d5f87d5..bb6e18c 100644 --- a/doc/sphinx/users-guide/running.rst +++ b/doc/sphinx/users-guide/running.rst @@ -11,6 +11,7 @@ securing and protecting Varnish against attacks. .. toctree:: :maxdepth: 2 + run_security command-line storage-backends params From phk at varnish-cache.org Mon Sep 23 18:10:21 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 23 Sep 2013 20:10:21 +0200 Subject: [master] 0d88c11 Remove the last traces of saint-mode from the core code. Message-ID: commit 0d88c116717abf633bd4e760e52b70d574ce4523 Author: Poul-Henning Kamp Date: Mon Sep 23 18:10:05 2013 +0000 Remove the last traces of saint-mode from the core code. diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c index 0b8b387..f626552 100644 --- a/bin/varnishd/cache/cache_backend.c +++ b/bin/varnishd/cache/cache_backend.c @@ -220,14 +220,7 @@ vbe_NewConn(void) } /*-------------------------------------------------------------------- - * It evaluates if a backend is healthy _for_a_specific_object_. - * That means that it relies on req->objcore->objhead. This is mainly for - * saint-mode, but also takes backend->healthy into account. If - * cache_param->saintmode_threshold is 0, this is basically just a test of - * backend->healthy. - * - * The threshold has to be evaluated _after_ the timeout check, otherwise - * items would never time out once the threshold is reached. + * Test if backend is healthy and report when it last changed */ unsigned diff --git a/bin/varnishd/common/params.h b/bin/varnishd/common/params.h index dc5f234..f990354 100644 --- a/bin/varnishd/common/params.h +++ b/bin/varnishd/common/params.h @@ -188,9 +188,6 @@ struct params { /* How long time does the ban lurker sleep */ double ban_lurker_sleep; - /* Max size of the saintmode list. 0 == no saint mode. */ - unsigned saintmode_threshold; - unsigned syslog_cli_traffic; unsigned http_range_support; diff --git a/bin/varnishd/mgt/mgt_param_tbl.c b/bin/varnishd/mgt/mgt_param_tbl.c index ab4094b..311abe9 100644 --- a/bin/varnishd/mgt/mgt_param_tbl.c +++ b/bin/varnishd/mgt/mgt_param_tbl.c @@ -439,13 +439,6 @@ const struct parspec mgt_parspec[] = { "A value of zero disables the ban lurker.", 0, "0.01", "s" }, - { "saintmode_threshold", tweak_uint, - &mgt_param.saintmode_threshold, 0, UINT_MAX, - "The maximum number of objects held off by saint mode before " - "no further will be made to the backend until one times out. " - "A value of 0 disables saintmode.", - EXPERIMENTAL, - "10", "objects" }, { "http_range_support", tweak_bool, &mgt_param.http_range_support, 0, 0, "Enable support for HTTP Range headers.\n", 0, From phk at varnish-cache.org Mon Sep 23 19:09:36 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 23 Sep 2013 21:09:36 +0200 Subject: [master] d65d7c7 Fix spacing in an error message Message-ID: commit d65d7c73a2e6beb8b9a92f3535d596423963d28a Author: Poul-Henning Kamp Date: Mon Sep 23 19:09:24 2013 +0000 Fix spacing in an error message diff --git a/bin/varnishtest/tests/m00003.vtc b/bin/varnishtest/tests/m00003.vtc index 0251a77..d1e36c2 100644 --- a/bin/varnishtest/tests/m00003.vtc +++ b/bin/varnishtest/tests/m00003.vtc @@ -26,6 +26,6 @@ client c1 { expect resp.http.bar == "foo" } -run -varnish v1 -errvcl {Expected 'from path...'} { +varnish v1 -errvcl {Expected 'from path ...'} { import std to; } diff --git a/bin/varnishtest/tests/m00008.vtc b/bin/varnishtest/tests/m00008.vtc index 30d39b7..c9d2bd8 100644 --- a/bin/varnishtest/tests/m00008.vtc +++ b/bin/varnishtest/tests/m00008.vtc @@ -11,7 +11,7 @@ varnish v1 -vcl+backend { varnish v1 -cliok "param.set vcc_unsafe_path off" -varnish v1 -errvcl {'import ... from path...' not allowed.} { +varnish v1 -errvcl {'import ... from path ...' not allowed.} { backend default { .host = "${s1_sock}"; } import std from "${topbuild}/lib/libvmod_std/.libs/libvmod_std.so" ; } diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c index 7eb9d32c..a2dc029 100644 --- a/lib/libvcc/vcc_vmod.c +++ b/lib/libvcc/vcc_vmod.c @@ -85,14 +85,13 @@ vcc_ParseImport(struct vcc *tl) if (tl->t->tok == ID) { if (!tl->unsafe_path) { VSB_printf(tl->sb, - "'import ... from path...'" - " not allowed.\nAt:"); + "'import ... from path ...' not allowed.\nAt:"); vcc_ErrToken(tl, tl->t); vcc_ErrWhere(tl, tl->t); return; } if (!vcc_IdIs(tl->t, "from")) { - VSB_printf(tl->sb, "Expected 'from path...'\n"); + VSB_printf(tl->sb, "Expected 'from path ...'\n"); vcc_ErrWhere(tl, tl->t); return; } From phk at varnish-cache.org Mon Sep 23 19:10:24 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 23 Sep 2013 21:10:24 +0200 Subject: [master] 52188d0 Default vcc_allow_inline_c to false in V4 Message-ID: commit 52188d046988d23320560c27f8da0105e3bb673c Author: Poul-Henning Kamp Date: Mon Sep 23 19:09:59 2013 +0000 Default vcc_allow_inline_c to false in V4 diff --git a/bin/varnishd/mgt/mgt_param_tbl.c b/bin/varnishd/mgt/mgt_param_tbl.c index 311abe9..6086c9c 100644 --- a/bin/varnishd/mgt/mgt_param_tbl.c +++ b/bin/varnishd/mgt/mgt_param_tbl.c @@ -522,7 +522,7 @@ const struct parspec mgt_parspec[] = { { "vcc_allow_inline_c", tweak_bool, &mgt_vcc_allow_inline_c, 0, 0, "Allow inline C code in VCL.\n", 0, - "on", "bool" }, + "off", "bool" }, { "vcc_unsafe_path", tweak_bool, &mgt_vcc_unsafe_path, 0, 0, "Allow '/' in vmod & include paths.\n" diff --git a/bin/varnishtest/tests/c00052.vtc b/bin/varnishtest/tests/c00052.vtc index 5de1430..2ab6c1a 100644 --- a/bin/varnishtest/tests/c00052.vtc +++ b/bin/varnishtest/tests/c00052.vtc @@ -7,7 +7,7 @@ server s1 { varnish v1 -varnish v1 -cliok "param.show vcc_allow_inline_c" +varnish v1 -cliok "param.set vcc_allow_inline_c true" varnish v1 -vcl+backend { C{ getpid(); }C diff --git a/bin/varnishtest/tests/c00055.vtc b/bin/varnishtest/tests/c00055.vtc index ae98b48..ff13f66 100644 --- a/bin/varnishtest/tests/c00055.vtc +++ b/bin/varnishtest/tests/c00055.vtc @@ -10,7 +10,7 @@ server s1 { txresp -status 200 -hdr "Foo: Foo" -body "56" } -start -varnish v1 -vcl+backend { +varnish v1 -cliok "param.set vcc_allow_inline_c true" -vcl+backend { sub vcl_recv { C{ VRT_CacheReqBody(ctx, 1000); }C return (pass); diff --git a/bin/varnishtest/tests/c00057.vtc b/bin/varnishtest/tests/c00057.vtc index 5ac6cee..55c478e 100644 --- a/bin/varnishtest/tests/c00057.vtc +++ b/bin/varnishtest/tests/c00057.vtc @@ -5,7 +5,9 @@ server s1 { txresp } -start -varnish v1 -cliok "param.set sigsegv_handler on" -vcl+backend { +varnish v1 -cliok "param.set vcc_allow_inline_c true" +varnish v1 -cliok "param.set sigsegv_handler on" +varnish v1 -vcl+backend { C{ #include #include diff --git a/bin/varnishtest/tests/r00742.vtc b/bin/varnishtest/tests/r00742.vtc index 9005fec..008f2f7 100644 --- a/bin/varnishtest/tests/r00742.vtc +++ b/bin/varnishtest/tests/r00742.vtc @@ -5,7 +5,7 @@ server s1 { txresp } -start -varnish v1 -vcl+backend { +varnish v1 -cliok "param.set vcc_allow_inline_c true" -vcl+backend { C{ void foo(void) { diff --git a/bin/varnishtest/tests/v00019.vtc b/bin/varnishtest/tests/v00019.vtc index b8e5466..c4bd725 100644 --- a/bin/varnishtest/tests/v00019.vtc +++ b/bin/varnishtest/tests/v00019.vtc @@ -23,7 +23,7 @@ varnish v1 -errvcl {Unterminated string at} { " } -varnish v1 -vcl { +varnish v1 -cliok "param.set vcc_allow_inline_c true" -vcl { backend b { .host = "127.0.0.1"; } sub vcl_recv { C{ int i; (void)i; }C } } diff --git a/bin/varnishtest/tests/v00020.vtc b/bin/varnishtest/tests/v00020.vtc index aac5776..2a98d30 100644 --- a/bin/varnishtest/tests/v00020.vtc +++ b/bin/varnishtest/tests/v00020.vtc @@ -1,6 +1,6 @@ varnishtest "VCL compiler coverage test: vcc_parse.c & vcc_expr.c" -varnish v1 -vcl { +varnish v1 -cliok "param.set vcc_allow_inline_c true" -vcl { backend b { .host = "127.0.0.1"; } C{ #include From phk at varnish-cache.org Mon Sep 23 20:24:33 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 23 Sep 2013 22:24:33 +0200 Subject: [master] e8a296c Add a requirement for VCL programs to declare their version like this: Message-ID: commit e8a296ca43b3346550e9f35c267c38d7ee265843 Author: Poul-Henning Kamp Date: Mon Sep 23 20:21:49 2013 +0000 Add a requirement for VCL programs to declare their version like this: vcl 4.0; The first token, after 'include' expansion, has to be such a declaration, which means that unless the first token in it is 'include' the file you give to -f, vcl.load or vcl.inline, must start out with "vcl 4.0;" The point about this is user-support and being able to offer better backwards compatibility in the future. diff --git a/bin/varnishd/default.vcl b/bin/varnishd/default.vcl index db64791..5240164 100644 --- a/bin/varnishd/default.vcl +++ b/bin/varnishd/default.vcl @@ -39,6 +39,8 @@ * -b argument. */ +vcl 4.0; + sub vcl_recv { if (req.restarts == 0) { if (req.http.x-forwarded-for) { diff --git a/bin/varnishd/mgt/mgt_vcc.c b/bin/varnishd/mgt/mgt_vcc.c index 6701436..4df7b0f 100644 --- a/bin/varnishd/mgt/mgt_vcc.c +++ b/bin/varnishd/mgt/mgt_vcc.c @@ -402,6 +402,7 @@ mgt_vcc_default(const char *b_arg, const char *f_arg, char *vcl, int C_flag) * XXX: again: we should check it here in the "trivial" case. */ bprintf(buf, + "vcl 4.0;\n" "backend default {\n" " .host = \"%s\";\n" "}\n", b_arg); diff --git a/bin/varnishtest/tests/b00014.vtc b/bin/varnishtest/tests/b00014.vtc index b68c79e..8c5822e 100644 --- a/bin/varnishtest/tests/b00014.vtc +++ b/bin/varnishtest/tests/b00014.vtc @@ -10,7 +10,7 @@ server s1 { txresp -body "bar" } -start -shell "echo 'backend foo { .host = \"${s1_addr}\"; .port = \"${s1_port}\"; }' > ${tmpdir}/_b00014.vcl" +shell "echo 'vcl 4.0; backend foo { .host = \"${s1_addr}\"; .port = \"${s1_port}\"; }' > ${tmpdir}/_b00014.vcl" varnish v1 -arg "-f ${tmpdir}/_b00014.vcl" -start client c1 { diff --git a/bin/varnishtest/vtc_varnish.c b/bin/varnishtest/vtc_varnish.c index ff8cfa2..9e9733f 100644 --- a/bin/varnishtest/vtc_varnish.c +++ b/bin/varnishtest/vtc_varnish.c @@ -644,7 +644,7 @@ varnish_vcl(struct varnish *v, const char *vcl, enum VCLI_status_e expect, char vsb = VSB_new_auto(); AN(vsb); - VSB_printf(vsb, "vcl.inline vcl%d << %s\n%s\n%s\n", + VSB_printf(vsb, "vcl.inline vcl%d << %s\nvcl 4.0;\n%s\n%s\n", ++v->vcl_nbr, NONSENSE, vcl, NONSENSE); AZ(VSB_finish(vsb)); @@ -688,7 +688,10 @@ varnish_vclbackend(struct varnish *v, const char *vcl) vsb2 = VSB_new_auto(); AN(vsb2); + VSB_printf(vsb2, "vcl 4.0;\n"); + cmd_server_genvcl(vsb2); + AZ(VSB_finish(vsb2)); VSB_printf(vsb, "vcl.inline vcl%d << %s\n%s\n%s\n%s\n", diff --git a/lib/libvcc/vcc_acl.c b/lib/libvcc/vcc_acl.c index fa8a7d7..433d848 100644 --- a/lib/libvcc/vcc_acl.c +++ b/lib/libvcc/vcc_acl.c @@ -462,7 +462,7 @@ vcc_Acl_Hack(struct vcc *tl, char *b) } void -vcc_Acl(struct vcc *tl) +vcc_ParseAcl(struct vcc *tl) { struct token *an; int i; diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h index b0983cc..cd72db9 100644 --- a/lib/libvcc/vcc_compile.h +++ b/lib/libvcc/vcc_compile.h @@ -219,7 +219,7 @@ struct method { /* vcc_acl.c */ -void vcc_Acl(struct vcc *tl); +void vcc_ParseAcl(struct vcc *tl); void vcc_Acl_Hack(struct vcc *tl, char *b); /* vcc_action.c */ @@ -265,6 +265,7 @@ char *TlDupTok(struct vcc *tl, const struct token *tok); void EncString(struct vsb *sb, const char *b, const char *e, int mode); /* vcc_expr.c */ +double vcc_DoubleVal(struct vcc *tl); void vcc_Duration(struct vcc *tl, double *); unsigned vcc_UintVal(struct vcc *tl); void vcc_Expr(struct vcc *tl, enum var_type typ); diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c index 164a8d6..33a59b1 100644 --- a/lib/libvcc/vcc_expr.c +++ b/lib/libvcc/vcc_expr.c @@ -141,7 +141,7 @@ vcc_NumVal(struct vcc *tl, double *d, int *frac) vcc_NextToken(tl); } -static double +double vcc_DoubleVal(struct vcc *tl) { double d; diff --git a/lib/libvcc/vcc_parse.c b/lib/libvcc/vcc_parse.c index ab562f5..9a7c56a 100644 --- a/lib/libvcc/vcc_parse.c +++ b/lib/libvcc/vcc_parse.c @@ -206,7 +206,7 @@ vcc_Compound(struct vcc *tl) */ static void -vcc_Function(struct vcc *tl) +vcc_ParseFunction(struct vcc *tl) { int m, i; @@ -277,18 +277,43 @@ vcc_Function(struct vcc *tl) */ static void -vcc_Director(struct vcc *tl) +vcc_ParseDirector(struct vcc *tl) { VSB_printf(tl->sb, "\ndirectors are now in directors VMOD.\n"); vcc_ErrWhere(tl, tl->t); } /*-------------------------------------------------------------------- + */ + +static void +vcc_ParseVcl(struct vcc *tl) +{ + double ver; + struct token *tok; + + assert(vcc_IdIs(tl->t, "vcl")); + vcc_NextToken(tl); + tok = tl->t; + ver = vcc_DoubleVal(tl); + ERRCHK(tl); + if (ver != 4.0) { + VSB_printf(tl->sb, "VCL version %.1f not supported.\n", ver); + vcc_ErrWhere(tl, tok); + ERRCHK(tl); + } + ExpectErr(tl, ';'); + vcc_NextToken(tl); +} + +/*-------------------------------------------------------------------- * Top level of parser, recognize: * Inline C-code * ACL definitions * Function definitions - * Backend & Director definitions + * Backend definitions + * VMOD import directives + * VCL version declarations * End of input */ @@ -298,12 +323,13 @@ static struct toplev { const char *name; parse_f *func; } toplev[] = { - { "acl", vcc_Acl }, - { "sub", vcc_Function }, + { "acl", vcc_ParseAcl }, + { "sub", vcc_ParseFunction }, { "backend", vcc_ParseBackend }, - { "director", vcc_Director }, + { "director", vcc_ParseDirector }, { "probe", vcc_ParseProbe }, { "import", vcc_ParseImport }, + { "vcl", vcc_ParseVcl }, { NULL, NULL } }; @@ -312,6 +338,18 @@ vcc_Parse(struct vcc *tl) { struct toplev *tp; + if (!vcc_IdIs(tl->t, "vcl")) { + VSB_printf(tl->sb, + "VCL version declaration missing\n" + "Update your VCL to Version 4 syntax, and add\n" + "\tvcl 4.0;\n" + "on the first line the VCL files.\n" + ); + vcc_ErrWhere(tl, tl->t); + ERRCHK(tl); + } + vcc_ParseVcl(tl); + ERRCHK(tl); while (tl->t->tok != EOI) { ERRCHK(tl); switch (tl->t->tok) { From phk at varnish-cache.org Mon Sep 23 20:24:33 2013 From: phk at varnish-cache.org (Poul-Henning Kamp) Date: Mon, 23 Sep 2013 22:24:33 +0200 Subject: [master] 4d9b05f Polish the "securit first" chapter some more Message-ID: commit 4d9b05fe47774c88736e8fc32bf901d6f69df75c Author: Poul-Henning Kamp Date: Mon Sep 23 19:23:20 2013 +0000 Polish the "securit first" chapter some more diff --git a/doc/sphinx/reference/varnish-cli.rst b/doc/sphinx/reference/varnish-cli.rst index 2411368..834a776 100644 --- a/doc/sphinx/reference/varnish-cli.rst +++ b/doc/sphinx/reference/varnish-cli.rst @@ -216,8 +216,10 @@ the NL character. For your reference the sourcefile lib/libvarnish/cli_common.h contains the functions varnish code uses to read and write CLI response. -Details on authentication -------------------------- +.. _ref_psk_auth: + +How -S/PSK Authentication Works +------------------------------- If the -S secret-file is given as argument to varnishd, all network CLI connections must authenticate, by proving they know the contents diff --git a/doc/sphinx/users-guide/run_security.rst b/doc/sphinx/users-guide/run_security.rst index 26a6b53..09d6314 100644 --- a/doc/sphinx/users-guide/run_security.rst +++ b/doc/sphinx/users-guide/run_security.rst @@ -5,7 +5,8 @@ Security first If you are the only person involved in running Varnish, or if all the people involved are trusted to the same degree, you can skip -this chapter. +this chapter: We have protected Varnish as well as we can from +anything which can come in through HTTP socket. If parts of your web infrastructure are outsourced or otherwise partitioned along adminitrative lines, you need to think about @@ -25,19 +26,21 @@ how and where the command comes into Varnish: Command line arguments ---------------------- -The top level security decisions is taken from the command line, -in order to make them invulnerable to subsequent manipulation. +The top level security decisions is taken on and from the command +line, in order to make them invulnerable to subsequent manipulation. The important decisions to make are: #. Who should have access to the Command Line Interface ? -#. Which parameters can the change ? +#. Which parameters can they change ? #. Will inline-C code be allowed ? -#. Will VMODs be restricted. +#. If/how VMODs will be restricted ? +CLI interface access +^^^^^^^^^^^^^^^^^^^^ The most important of these is the CLI interface: Should it be accessible only on the local machine, or should it be accessible @@ -47,82 +50,123 @@ No matter what you do, you should always protect the CLI with a Pre-Shared-Key (The -S argument). The way -S/PSK works is really simple: You specify -S and filename, -and only somebody who knows what is in that file can access the CLI. +and only somebody who knows the exact contents of that file can +access the CLI. By protecting the secret file with suitable UNIX +permissions, you can restrict CLI access -They do not need to be able to read that specific file on that -specific machine, as long as they know *exactly* what is in that file. +The varnishadm(8) program knows how to do the -S/PSK protocol, +both locally and remote. -If the CLI should only be available on the local machine, bind the -CLI port to a loopback IP number ("-T 127.0.0.1"). +(XXX ref: user-guide: setting up -S) + +The CLI port is a TCP socket, and it can be bound to any IP +number+socket combination the kernel will accept:: + + -T 127.0.0.1:631 + -T localhost:9999 + -T 192.168.1.1:34 + -T '[fe80::1]:8082' If you want to be able to use the CLI remotely, you can do it -two ways: +two ways. You can bind the CLI port to a reachable IP number, and connect -directly. This gives you no secrecy, the CLI commands will -go across the network as ASCII test with no encryption. +directly. This gives you no secrecy, ie, the CLI commands will +go across the network as ASCII text with no encryption, but +using the -S option, you will get authentication. + +Alternatively you can bind the CLI port to a 'localhost' address, +and give remote users access via a secure connection to the local +machine (ssh, VPN, etc. etc.) + +It is also possible to configure varnishd for "reverse mode", using +the '-M' argument, + +In this case varnishd will attempt to open a TCP connection to the +specified address, and initiate a CLI connection on it. + +The connection is also in this case without secrecy, but if configured +the remote end must still satisfy -S/PSK authentication. -Or you can bind the CLI port locally, and give remote users access -via a secure connection to the local machine (ssh, VPN, etc. etc.) +Parameters +^^^^^^^^^^ -It is also possible to configure varnishd for "reverse mode", where -varnishd will attempt to open a TCP connection to a specified -address, and initiate a CLI connection on it. This is meant to -make it easier to manage a cluster of varnish machines from a single -"cluster controller" process. +Parameters can be set from the command line, and made "read-only" +(using -r) so they cannot subsequently be modified from the CLI +interface. -Other parameters to consider are the uid/gid of the child process. +Pretty much any parameter can be used to totally mess up your +HTTP service, but a few can do more damage than that:: + + user -- access to local system via VCL + group -- access to local system via VCL + listen_address -- trojan other service ports (ssh!) + cc_command -- execute arbitrary programs + +Furthermore you may want to look at:: + + syslog_cli_traffic -- know what is going on + vcc_unsafe_path -- retrict VCL/VMODS to vcl_dir+vmod_dir + vcl_dir -- VCL include dir + vmod_dir -- VMOD import dir The CLI interface ----------------- The CLI interface in Varnish is very powerful, if you have access to the CLI interface, you can do almost anything to -the varnish process. +the Varnish process. -Some restrictions can be put in place from the command line arguments, -for instance specific parameters can be made Read-Only with the -r -argument, which prevents changes to them from the CLI. +As described above, some of the damage can be limited by restricting +certain parameters, but that will only protect the local filesystem, +and operating system, it will not protect your HTTP service. We do not currently have a way to restrict specific CLI commands -to specific CLI connections. (One way to get such an effect is to -not "wrap" all CLI access in pre-approved scripts which use -varnishadm(1) to submit the sanitized CLI commands, and restrict a -remote user to only those scripts in sshd(8)'s configuration.) +to specific CLI connections. One way to get such an effect is to +"wrap" all CLI access in pre-approved scripts which use varnishadm(1) +to submit the sanitized CLI commands, and restrict a remote user +to only those scripts in sshd(8)'s configuration. VCL programs ------------ -There are two "dangerous" mechnisms available in VCL code: VMODs +There are two "dangerous" mechanisms available in VCL code: VMODs and inline-C. Both of these mechanisms allow execution of arbitrary code and will -therefore allow a person to get shell access on the computer. -(XXX: doc which privs) +therefore allow a person to get access on the computer, with the +privileges of the child process. -Inline C can be disabled with the parameter "vcc_allow_inline_c", -remember to make it read-only from the commandline if you don't -trust the CLI wranglers to leave it alone. +If varnishd is started as root/superuser, we sandbox the child +process, using whatever facilities are available on the operating +system, but if varnishd is not started as root/superuser, this is +not possible. No, don't ask me why you have to be superuser to +lower the privilege of a child process... -VMODs can be restricted to be loaded only from the path specified -using parameter 'vmod_dir' using the 'vcc_unsafe_path' parameter. -Again: remember to make the read-only. +Inline-C is disabled by default starting with Varnish 4, so unless +you enable it, you don't have to worry about it. -If you do this, we belive that the integrity of the machine -running varnishd, cannot be compromised from the VCL program, -but it will be possible to read files available to the child -process. +The params mentioned above can restrict VMOD so they can only +be imported from a designated directory, restricting VCL wranglers +to a pre-approved subset of VMODs. + +If you do that, we belive that your local system cannot be compromised +from VCL code. HTTP requests ------------- -We have gone to great lengths to make varnish resistant to anything -coming in throught he socket where HTTP requests are received, -but given that VCL is a programming language which lets you +We have gone to great lengths to make Varnish resistant to anything +coming in throught he socket where HTTP requests are received, and +you should, generally speaking, not need to protect it any further. + +The caveat is that since VCL is a programming language which lets you decide exactly what to do about HTTP requests, you can also decide -to do stupid things to them. +to do exactly stupid things to them, including opening youself up +to various kinds of attacks and subversive activities. -VCL offers a IP based Access-Control-List facility which allows you -to restrict certain requests, for instance PURGE, to certain IP -numbers/ranges. +If you have "administrative" HTTP requests, for instance PURGE +requests, we recommend that you restrict them to trusted IP +numbers/nets using VCL's Access Control Lists. +(XXX: missing ref to ACL) From tfheen at varnish-cache.org Tue Sep 24 08:03:18 2013 From: tfheen at varnish-cache.org (Tollef Fog Heen) Date: Tue, 24 Sep 2013 10:03:18 +0200 Subject: [master] 00090ea Fix up doc building Message-ID: commit 00090ea3b6b5d47f9392ec622ac85c7a119e28f4 Author: Tollef Fog Heen Date: Tue Sep 24 10:02:09 2013 +0200 Fix up doc building Unbreak build after 988cd77462865f25d76db1684df183125565e359 shuffled file names around without changing the corresponding Makefile. diff --git a/doc/sphinx/Makefile.am b/doc/sphinx/Makefile.am index 579b6c8..1ba6eb1 100644 --- a/doc/sphinx/Makefile.am +++ b/doc/sphinx/Makefile.am @@ -136,18 +136,21 @@ EXTRA_DIST = \ tutorial/now_what.rst \ users-guide/command-line.rst \ users-guide/compression.rst \ - users-guide/configuration.rst \ users-guide/cookies.rst \ users-guide/devicedetection.rst \ users-guide/esi.rst \ users-guide/increasing-your-hitrate.rst \ users-guide/index.rst \ + users-guide/intro.rst \ users-guide/operation-cli.rst \ users-guide/operation-logging.rst \ users-guide/operation.rst \ users-guide/operation-statistics.rst \ users-guide/params.rst \ + users-guide/performance.rst \ users-guide/purging.rst \ + users-guide/report.rst \ + users-guide/running.rst \ users-guide/sizing-your-cache.rst \ users-guide/storage-backends.rst \ users-guide/troubleshooting.rst \ From phk at phk.freebsd.dk Tue Sep 24 08:54:53 2013 From: phk at phk.freebsd.dk (Poul-Henning Kamp) Date: Tue, 24 Sep 2013 08:54:53 +0000 Subject: [master] 00090ea Fix up doc building In-Reply-To: References: Message-ID: <2076.1380012893@critter.freebsd.dk> In message , Tollef Fog Heen wr ites: > Unbreak build after 988cd77462865f25d76db1684df183125565e359 shuffled > file names around without changing the corresponding Makefile. Ohh.. eeh.. sorry ? Is this for the dist* targets ? -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 phk at FreeBSD.ORG | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence. From perbu at varnish-cache.org Mon Sep 30 12:10:21 2013 From: perbu at varnish-cache.org (Per Buer) Date: Mon, 30 Sep 2013 14:10:21 +0200 Subject: [master] 5eebc0f typo Message-ID: commit 5eebc0f5967a25ca12f702139a7e77e680564296 Author: Per Buer Date: Mon Sep 30 14:10:16 2013 +0200 typo diff --git a/doc/sphinx/users-guide/purging.rst b/doc/sphinx/users-guide/purging.rst index 668cacf..3c652ea 100644 --- a/doc/sphinx/users-guide/purging.rst +++ b/doc/sphinx/users-guide/purging.rst @@ -57,7 +57,7 @@ following VCL in place:: } } -As you can see we have used to new VCL subroutines, vcl_hit and +As you can see we have used two new VCL subroutines, vcl_hit and vcl_miss. When we call lookup Varnish will try to lookup the object in its cache. It will either hit an object or miss it and so the corresponding subroutine is called. In vcl_hit the object that is