예제 #1
0
/*
 * The helper program receives queries on stdin, one
 * per line, and must return the result on on stdout
 */
static void
refreshCheckHandleReply(void *data, char *reply)
{
    refreshCheckState *state = data;
    refreshCheckState *next;
    int freshness = -1;
    char *log = NULL;
    MemBuf hdrs = MemBufNULL;


    debug(84, 2) ("refreshCheckHandleReply: reply=\"%s\"\n", reply);

    if (reply) {
	char *t = NULL;
	char *token = strwordtok(reply, &t);
	if (token && strcmp(token, "FRESH") == 0)
	    freshness = 0;
	else if (token && strcmp(token, "OK") == 0)
	    freshness = 0;

	while ((token = strwordtok(NULL, &t))) {
	    char *value = strchr(token, '=');
	    if (value) {
		*value++ = '\0';	/* terminate the token, and move up to the value */
		rfc1738_unescape(value);
		if (strcmp(token, "freshness") == 0)
		    freshness = atoi(value);
		else if (strcmp(token, "log") == 0)
		    log = value;
		else if (strncmp(token, "res{", 4) == 0) {
		    char *header, *t;
		    header = token + 4;
		    t = strrchr(header, '}');
		    if (!t)
			continue;
		    *t = '\0';
		    if (!hdrs.buf)
			memBufDefInit(&hdrs);
		    memBufPrintf(&hdrs, "%s: %s\r\n", header, value);
		}
	    }
	}
    }
    if (freshness >= 0) {
	if (hdrs.size) {
	    HttpReply *rep = httpReplyCreate();
	    httpHeaderParse(&rep->header, hdrs.buf, hdrs.buf + hdrs.size);
	    httpReplyUpdateOnNotModified(state->entry->mem_obj->reply, rep);
	    storeTimestampsSet(state->entry);
	    if (!httpHeaderHas(&rep->header, HDR_DATE)) {
		state->entry->timestamp = squid_curtime;
		state->entry->expires = squid_curtime + freshness;
	    } else if (freshness) {
		state->entry->expires = squid_curtime + freshness;
	    }
	    httpReplyDestroy(rep);
	    storeUpdate(state->entry, NULL);
	} else {
	    state->entry->timestamp = squid_curtime;
	    state->entry->expires = squid_curtime + freshness;
	}
    }
    if (hdrs.buf)
	memBufClean(&hdrs);
    dlinkDelete(&state->list, &state->def->queue);
    do {
	cbdataUnlock(state->def);
	state->def = NULL;

	if (state->callback && cbdataValid(state->callback_data))
	    state->callback(state->callback_data, freshness >= 0, log);
	cbdataUnlock(state->callback_data);
	state->callback_data = NULL;

	next = state->queue;
	cbdataFree(state);
	state = next;
    } while (state);
}
예제 #2
0
/* wait for full http headers to be received then parse them */
static void
peerDigestFetchReply(void *data, char *buf, ssize_t size)
{
    DigestFetchState *fetch = data;
    PeerDigest *pd = fetch->pd;
    size_t hdr_size;
    assert(pd && buf);
    assert(!fetch->offset);

    if (peerDigestFetchedEnough(fetch, buf, size, "peerDigestFetchReply"))
	return;

    if ((hdr_size = headersEnd(buf, size))) {
	http_status status;
	HttpReply *reply = fetch->entry->mem_obj->reply;
	assert(reply);
	httpReplyParse(reply, buf, hdr_size);
	status = reply->sline.status;
	debug(72, 3) ("peerDigestFetchReply: %s status: %d, expires: %d (%+d)\n",
	    strBuf(pd->host), status,
	    reply->expires, reply->expires - squid_curtime);

	/* this "if" is based on clientHandleIMSReply() */
	if (status == HTTP_NOT_MODIFIED) {
	    request_t *r = NULL;
	    /* our old entry is fine */
	    assert(fetch->old_entry);
	    if (!fetch->old_entry->mem_obj->request)
		fetch->old_entry->mem_obj->request = r =
		    requestLink(fetch->entry->mem_obj->request);
	    assert(fetch->old_entry->mem_obj->request);
	    httpReplyUpdateOnNotModified(fetch->old_entry->mem_obj->reply, reply);
	    storeTimestampsSet(fetch->old_entry);
	    /* get rid of 304 reply */
	    storeUnregister(fetch->entry, fetch);
	    storeUnlockObject(fetch->entry);
	    fetch->entry = fetch->old_entry;
	    fetch->old_entry = NULL;
	    /* preserve request -- we need its size to update counters */
	    /* requestUnlink(r); */
	    /* fetch->entry->mem_obj->request = NULL; */
	} else if (status == HTTP_OK) {
	    /* get rid of old entry if any */
	    if (fetch->old_entry) {
		debug(72, 3) ("peerDigestFetchReply: got new digest, releasing old one\n");
		storeUnregister(fetch->old_entry, fetch);
		storeReleaseRequest(fetch->old_entry);
		storeUnlockObject(fetch->old_entry);
		fetch->old_entry = NULL;
	    }
	} else {
	    /* some kind of a bug */
	    peerDigestFetchAbort(fetch, buf, httpStatusLineReason(&reply->sline));
	    return;
	}
	/* must have a ready-to-use store entry if we got here */
	/* can we stay with the old in-memory digest? */
	if (status == HTTP_NOT_MODIFIED && fetch->pd->cd)
	    peerDigestFetchStop(fetch, buf, "Not modified");
	else
	    storeClientCopy(fetch->entry,	/* have to swap in */
		0, 0, SM_PAGE_SIZE, buf, peerDigestSwapInHeaders, fetch);
    } else {
	/* need more data, do we have space? */
	if (size >= SM_PAGE_SIZE)
	    peerDigestFetchAbort(fetch, buf, "reply header too big");
	else
	    storeClientCopy(fetch->entry, size, 0, SM_PAGE_SIZE, buf,
		peerDigestFetchReply, fetch);
    }
}
예제 #3
0
/* wait for full http headers to be received */
static void
peerDigestFetchReply(void *data, mem_node_ref nr, ssize_t size)
{
    const char *buf = nr.node->data + nr.offset;
    DigestFetchState *fetch = data;
    PeerDigest *pd = fetch->pd;
    http_status status;
    HttpReply *reply;
    assert(pd && buf);
    assert(!fetch->offset);
    assert(size <= nr.node->len - nr.offset);

    if (peerDigestFetchedEnough(fetch, size, "peerDigestFetchReply"))
	goto finish;

    reply = fetch->entry->mem_obj->reply;
    assert(reply);
    status = reply->sline.status;
    debug(72, 3) ("peerDigestFetchReply: %s status: %d, expires: %ld (%+d)\n",
	strBuf(pd->host), status,
	(long int) reply->expires, (int) (reply->expires - squid_curtime));

    /* this "if" is based on clientHandleIMSReply() */
    if (status == HTTP_NOT_MODIFIED) {
	request_t *r = NULL;
	/* our old entry is fine */
	assert(fetch->old_entry);
	if (!fetch->old_entry->mem_obj->request)
	    fetch->old_entry->mem_obj->request = r =
		requestLink(fetch->entry->mem_obj->request);
	assert(fetch->old_entry->mem_obj->request);
	httpReplyUpdateOnNotModified(fetch->old_entry->mem_obj->reply, reply);
	storeTimestampsSet(fetch->old_entry);
	/* get rid of 304 reply */
	storeClientUnregister(fetch->sc, fetch->entry, fetch);
	storeUnlockObject(fetch->entry);
	/* And prepare to swap in old entry if needed */
	fetch->entry = fetch->old_entry;
	fetch->old_entry = NULL;
	fetch->sc = fetch->old_sc;
	fetch->old_sc = NULL;
	/* preserve request -- we need its size to update counters */
	/* requestUnlink(r); */
	/* fetch->entry->mem_obj->request = NULL; */
    } else if (status == HTTP_OK) {
	/* get rid of old entry if any */
	if (fetch->old_entry) {
	    debug(72, 3) ("peerDigestFetchReply: got new digest, releasing old one\n");
	    storeClientUnregister(fetch->old_sc, fetch->old_entry, fetch);
	    storeReleaseRequest(fetch->old_entry);
	    storeUnlockObject(fetch->old_entry);
	    fetch->old_entry = NULL;
	}
    } else {
	/* some kind of a bug */
	peerDigestFetchAbort(fetch, httpStatusLineReason(&reply->sline));
	goto finish;
    }
    /* must have a ready-to-use store entry if we got here */
    /* can we stay with the old in-memory digest? */
    if (status == HTTP_NOT_MODIFIED && fetch->pd->cd)
	peerDigestFetchStop(fetch, "Not modified");
    else
	storeClientRef(fetch->sc, fetch->entry,		/* have to swap in */
	    0, 0, SM_PAGE_SIZE, peerDigestSwapInHeaders, fetch);
  finish:
    stmemNodeUnref(&nr);
}