Пример #1
0
static void
tst(const char *s, time_t good)
{
	time_t t;
	char buf[BUFSIZ];

	t = TIM_parse(s);
	TIM_format(t, buf);
	printf("%-30s -> %12jd -> %s\n", s, (intmax_t)t, buf);
	if (t != good) {
		printf("Parse error! Got: %jd should have %jd diff %jd\n",
		    (intmax_t)t, (intmax_t)good, (intmax_t)(t - good));
		exit (2);
	}
}
Пример #2
0
int
main(int argc, char **argv)
{
	time_t t;
	char buf[BUFSIZ];

	time(&t);
	memset(buf, 0x55, sizeof buf);
	TIM_format(t, buf);
	printf("scan = %d <%s>\n", TIM_parse(buf), buf);

	/* Examples from RFC2616 section 3.3.1 */
	tst("Sun, 06 Nov 1994 08:49:37 GMT", 784111777);
	tst("Sunday, 06-Nov-94 08:49:37 GMT", 784111777);
	tst("Sun Nov  6 08:49:37 1994", 784111777);

	tst_delta();

	return (0);
}
static int
cnt_fetch(struct sess *sp)
{
    int i, transient;
    struct http *hp, *hp2;
    char *b;
    unsigned handling;

    CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
    CHECK_OBJ_NOTNULL(sp->vcl, VCL_CONF_MAGIC);

    AN(sp->director);
    AZ(sp->vbe);

    /* sp->wrk->http[0] is (still) bereq */
    sp->wrk->beresp = &sp->wrk->http[1];
    http_Setup(sp->wrk->beresp, sp->wrk->ws);

    i = FetchHdr(sp);

    /*
     * Save a copy before it might get mangled in VCL.  When it comes to
     * dealing with the body, we want to see the unadultered headers.
     */
    sp->wrk->beresp1 = &sp->wrk->http[2];
    *sp->wrk->beresp1 = *sp->wrk->beresp;

    if (i) {
        if (sp->objhead) {
            CHECK_OBJ_NOTNULL(sp->objhead, OBJHEAD_MAGIC);
            CHECK_OBJ_NOTNULL(sp->objcore, OBJCORE_MAGIC);
            HSH_DerefObjCore(sp);
        }
        AZ(sp->obj);
        sp->wrk->bereq = NULL;
        sp->wrk->beresp = NULL;
        sp->wrk->beresp1 = NULL;
        sp->err_code = 503;
        sp->step = STP_ERROR;
        return (0);
    }

    sp->err_code = http_GetStatus(sp->wrk->beresp);

    /*
     * Initial cacheability determination per [RFC2616, 13.4]
     * We do not support ranges yet, so 206 is out.
     */
    switch (sp->err_code) {
    case 200: /* OK */
    case 203: /* Non-Authoritative Information */
    case 300: /* Multiple Choices */
    case 301: /* Moved Permanently */
    case 302: /* Moved Temporarily */
    case 410: /* Gone */
    case 404: /* Not Found */
        sp->wrk->cacheable = 1;
        break;
    default:
        sp->wrk->cacheable = 0;
        break;
    }

    sp->wrk->entered = TIM_real();
    sp->wrk->age = 0;
    sp->wrk->ttl = RFC2616_Ttl(sp);

    if (sp->wrk->ttl == 0.)
        sp->wrk->cacheable = 0;

    sp->wrk->do_esi = 0;
    sp->wrk->grace = NAN;

    VCL_fetch_method(sp);

    /*
     * When we fetch the body, we may hit the LRU cleanup and that
     * will overwrite sp->handling, so we have to save our plans
     * here.
     */
    handling = sp->handling;

    if (sp->objhead == NULL)
        transient = 1;
    else if (sp->handling == VCL_RET_DELIVER)
        transient = 0;
    else
        transient = 1;

    /*
     * XXX: If we have a Length: header, we should allocate the body
     * XXX: also.
     */
    sp->obj = HSH_NewObject(sp, transient);

    if (sp->objhead != NULL) {
        CHECK_OBJ_NOTNULL(sp->objhead, OBJHEAD_MAGIC);
        CHECK_OBJ_NOTNULL(sp->objcore, OBJCORE_MAGIC);
        sp->objcore->obj = sp->obj;
        sp->obj->objcore = sp->objcore;
        sp->obj->objhead = sp->objhead;
        sp->objhead = NULL;	/* refcnt follows pointer. */
        sp->objcore = NULL;	/* refcnt follows pointer. */
    }

    BAN_NewObj(sp->obj);

    sp->obj->xid = sp->xid;
    sp->obj->response = sp->err_code;
    sp->obj->cacheable = sp->wrk->cacheable;
    sp->obj->ttl = sp->wrk->ttl;
    sp->obj->grace = sp->wrk->grace;
    if (sp->obj->ttl == 0. && sp->obj->grace == 0.)
        sp->obj->cacheable = 0;
    sp->obj->age = sp->wrk->age;
    sp->obj->entered = sp->wrk->entered;
    WS_Assert(sp->obj->ws_o);

    /* Filter into object */
    hp = sp->wrk->beresp;
    hp2 = sp->obj->http;

    hp2->logtag = HTTP_Obj;
    http_CopyResp(hp2, hp);
    http_FilterFields(sp->wrk, sp->fd, hp2, hp, HTTPH_A_INS);
    http_CopyHome(sp->wrk, sp->fd, hp2);

    if (http_GetHdr(hp, H_Last_Modified, &b))
        sp->obj->last_modified = TIM_parse(b);

    i = FetchBody(sp);
    AZ(sp->wrk->wfd);
    AZ(sp->vbe);
    AN(sp->director);

    if (i) {
        HSH_Drop(sp);
        AZ(sp->obj);
        sp->wrk->bereq = NULL;
        sp->wrk->beresp = NULL;
        sp->wrk->beresp1 = NULL;
        sp->err_code = 503;
        sp->step = STP_ERROR;
        return (0);
    }

    if (!transient)
        HSH_Object(sp);

    if (sp->wrk->do_esi)
        ESI_Parse(sp);

    switch (handling) {
    case VCL_RET_RESTART:
        HSH_Drop(sp);
        sp->director = NULL;
        sp->restarts++;
        sp->wrk->bereq = NULL;
        sp->wrk->beresp = NULL;
        sp->wrk->beresp1 = NULL;
        sp->step = STP_RECV;
        return (0);
    case VCL_RET_PASS:
        if (sp->obj->objcore != NULL)
            sp->obj->objcore->flags |= OC_F_PASS;
        if (sp->obj->ttl - sp->t_req < params->default_ttl)
            sp->obj->ttl = sp->t_req + params->default_ttl;
        break;
    case VCL_RET_DELIVER:
        break;
    case VCL_RET_ERROR:
        HSH_Drop(sp);
        sp->wrk->bereq = NULL;
        sp->wrk->beresp = NULL;
        sp->wrk->beresp1 = NULL;
        sp->step = STP_ERROR;
        return (0);
    default:
        WRONG("Illegal action in vcl_fetch{}");
    }

    sp->obj->cacheable = 1;
    if (sp->obj->objhead != NULL) {
        VRY_Create(sp);
        EXP_Insert(sp->obj);
        AN(sp->obj->ban);
        HSH_Unbusy(sp);
    }
    sp->acct_req.fetch++;
    sp->wrk->bereq = NULL;
    sp->wrk->beresp = NULL;
    sp->wrk->beresp1 = NULL;
    sp->step = STP_DELIVER;
    return (0);
}
Пример #4
0
double
RFC2616_Ttl(const struct sess *sp)
{
	double ttl;
	unsigned max_age, age;
	double h_date, h_expires;
	char *p;
	const struct http *hp;

	hp = sp->wrk->beresp;

	assert(sp->wrk->entered != 0.0 && !isnan(sp->wrk->entered));
	/* If all else fails, cache using default ttl */
	ttl = params->default_ttl;

	max_age = age = 0;
	h_expires = 0;
	h_date = 0;

	/*
	 * Initial cacheability determination per [RFC2616, 13.4]
	 * We do not support ranges yet, so 206 is out.
	 */

	switch (sp->err_code) {
	default:
		sp->wrk->exp.ttl = -1.;
		break;
	case 200: /* OK */
	case 203: /* Non-Authoritative Information */
	case 300: /* Multiple Choices */
	case 301: /* Moved Permanently */
	case 302: /* Moved Temporarily */
	case 410: /* Gone */
	case 404: /* Not Found */
		/*
		 * First find any relative specification from the backend
		 * These take precedence according to RFC2616, 13.2.4
		 */

		if ((http_GetHdrField(hp, H_Cache_Control, "s-maxage", &p) ||
		    http_GetHdrField(hp, H_Cache_Control, "max-age", &p)) &&
		    p != NULL) {

			if (*p == '-')
				max_age = 0;
			else
				max_age = strtoul(p, NULL, 0);
			if (http_GetHdr(hp, H_Age, &p)) {
				age = strtoul(p, NULL, 0);
				sp->wrk->age = age;
			}

			if (age > max_age)
				ttl = 0;
			else
				ttl = max_age - age;
			break;
		}

		/* Next look for absolute specifications from backend */

		if (http_GetHdr(hp, H_Expires, &p))
			h_expires = TIM_parse(p);

		/* No expire header, fall back to default */
		if (h_expires == 0)
			break;

		if (http_GetHdr(hp, H_Date, &p))
			h_date = TIM_parse(p);

		/* If backend told us it is expired already, don't cache. */
		if (h_expires < h_date) {
			ttl = 0;
			break;
		}

		if (h_date == 0 ||
		    fabs(h_date - sp->wrk->entered) < params->clock_skew) {
			/*
			 * If we have no Date: header or if it is
			 * sufficiently close to our clock we will
			 * trust Expires: relative to our own clock.
			 */
			if (h_expires < sp->wrk->entered)
				ttl = 0;
			else
				ttl = h_expires - sp->wrk->entered;
			break;
		} else {
			/*
			 * But even if the clocks are out of whack we can still
			 * derive a relative time from the two headers.
			 * (the negative ttl case is caught above)
			 */
			ttl = (int)(h_expires - h_date);
		}

	}

	/* calculated TTL, Our time, Date, Expires, max-age, age */
	WSP(sp, SLT_TTL, "%u RFC %g %.0f %.0f %.0f %u %u", sp->xid,
	    ttl, sp->wrk->entered, h_date, h_expires, max_age, age);

	return (ttl);
}