Ejemplo n.º 1
0
/* free fetch state structures
 * must be called only when fetch cbdata is valid */
static void
peerDigestFetchFinish(DigestFetchState * fetch, int err)
{
    assert(fetch->entry && fetch->request);

    if (fetch->old_entry) {
	debug(72, 2) ("peerDigestFetchFinish: deleting old entry\n");
	storeUnregister(fetch->old_entry, fetch);
	storeReleaseRequest(fetch->old_entry);
	storeUnlockObject(fetch->old_entry);
	fetch->old_entry = NULL;
    }
    /* update global stats */
    kb_incr(&Counter.cd.kbytes_sent, (size_t) fetch->sent.bytes);
    kb_incr(&Counter.cd.kbytes_recv, (size_t) fetch->recv.bytes);
    Counter.cd.msgs_sent += fetch->sent.msg;
    Counter.cd.msgs_recv += fetch->recv.msg;

    /* unlock everything */
    storeUnregister(fetch->entry, fetch);
    storeUnlockObject(fetch->entry);
    requestUnlink(fetch->request);
    fetch->entry = NULL;
    fetch->request = NULL;
    assert(fetch->pd == NULL);
    cbdataUnlock(fetch);
    cbdataFree(fetch);
}
Ejemplo n.º 2
0
static void
free_StoreUpdateState(void *data)
{
    StoreUpdateState *state = data;
    if (state->sc)
	storeClientUnregister(state->sc, state->oldentry, state);
    if (state->oldentry)
	storeUnlockObject(state->oldentry);
    if (state->newentry) {
	/* Set to NULL on completion, so we only get here in abnormal situations */
	storeRelease(state->newentry);
	storeComplete(state->newentry);
	storeUnlockObject(state->newentry);
    }
}
Ejemplo n.º 3
0
static void
peerCountMcastPeersDone(void *data)
{
    ps_state *psstate = data;
    peer *p = psstate->callback_data;
    StoreEntry *fake = psstate->entry;
    if (cbdataValid(p)) {
	p->mcast.flags.counting = 0;
	p->mcast.avg_n_members = doubleAverage(p->mcast.avg_n_members,
	    (double) psstate->ping.n_recv,
	    ++p->mcast.n_times_counted,
	    10);
	debug(15, 1) ("Group %s: %d replies, %4.1f average, RTT %d\n",
	    p->host,
	    psstate->ping.n_recv,
	    p->mcast.avg_n_members,
	    p->stats.rtt);
	p->mcast.n_replies_expected = (int) p->mcast.avg_n_members;
    }
    cbdataUnlock(p);
    EBIT_SET(fake->flags, ENTRY_ABORTED);
    requestUnlink(fake->mem_obj->request);
    fake->mem_obj->request = NULL;
    storeReleaseRequest(fake);
    storeUnlockObject(fake);
    requestUnlink(psstate->request);
    cbdataFree(psstate);
}
Ejemplo n.º 4
0
static void
heap_purgeDone(RemovalPurgeWalker * walker)
{
    HeapPurgeData *heap_walker = walker->_data;
    RemovalPolicy *policy = walker->_policy;
    HeapPolicyData *heap = policy->_data;
    StoreEntry *entry;
    assert(strcmp(policy->_type, "heap") == 0);
    assert(heap->nwalkers > 0);
    heap->nwalkers -= 1;
    if (heap_walker->min_age > 0) {
	heap->heap->age = heap_walker->min_age;
	debug(81, 3) ("heap_purgeDone: Heap age set to %f\n",
	    (double) heap->heap->age);
    }
    /*
     * Reinsert the locked entries
     */
    while ((entry = linklistShift(&heap_walker->locked_entries))) {
	heap_node *node = heap_insert(heap->heap, entry);
	SET_POLICY_NODE(entry, node);
	storeUnlockObject(entry);
    }
    safe_free(walker->_data);
    cbdataFree(walker);
}
Ejemplo n.º 5
0
static void
mimeLoadIconFile(const char *icon)
{
    int fd;
    int n;
    request_flags flags;
    struct stat sb;
    StoreEntry *e;
    LOCAL_ARRAY(char, path, MAXPATHLEN);
    LOCAL_ARRAY(char, url, MAX_URL);
    char *buf;
    const char *type = mimeGetContentType(icon);
    HttpReply *reply;
    if (type == NULL)
	fatal("Unknown icon format while reading mime.conf\n");
    buf = internalLocalUri("/squid-internal-static/icons/", icon);
    xstrncpy(url, buf, MAX_URL);
    if (storeGetPublic(url, METHOD_GET))
	return;
    snprintf(path, MAXPATHLEN, "%s/%s", Config.icons.directory, icon);
    fd = file_open(path, O_RDONLY);
    if (fd < 0) {
	debug(25, 0) ("mimeLoadIconFile: %s: %s\n", path, xstrerror());
	return;
    }
    if (fstat(fd, &sb) < 0) {
	debug(50, 0) ("mimeLoadIconFile: FD %d: fstat: %s\n", fd, xstrerror());
	return;
    }
    flags = null_request_flags;
    flags.cachable = 1;
    e = storeCreateEntry(url,
	url,
	flags,
	METHOD_GET);
    assert(e != NULL);
    storeSetPublicKey(e);
    storeBuffer(e);
    e->mem_obj->request = requestLink(urlParse(METHOD_GET, url));
    httpReplyReset(reply = e->mem_obj->reply);
    httpReplySetHeaders(reply, 1.0, HTTP_OK, NULL,
	type, (int) sb.st_size, sb.st_mtime, -1);
    reply->cache_control = httpHdrCcCreate();
    httpHdrCcSetMaxAge(reply->cache_control, 86400);
    httpHeaderPutCc(&reply->header, reply->cache_control);
    httpReplySwapOut(reply, e);
    reply->hdr_sz = e->mem_obj->inmem_hi;	/* yuk */
    /* read the file into the buffer and append it to store */
    buf = memAllocate(MEM_4K_BUF);
    while ((n = read(fd, buf, 4096)) > 0)
	storeAppend(e, buf, n);
    file_close(fd);
    EBIT_SET(e->flags, ENTRY_SPECIAL);
    storeBufferFlush(e);
    storeComplete(e);
    storeTimestampsSet(e);
    debug(25, 3) ("Loaded icon %s\n", url);
    storeUnlockObject(e);
    memFree(buf, MEM_4K_BUF);
}
static void
whoisClose(int fd, void *data)
{
    WhoisState *p = data;
    debug(75, 3) ("whoisClose: FD %d\n", fd);
    storeUnlockObject(p->entry);
    cbdataFree(p);
}
Ejemplo n.º 7
0
static void
free_refreshCheckState(void *data)
{
    refreshCheckState *state = data;
    storeUnlockObject(state->entry);
    cbdataUnlock(state->callback_data);
    cbdataUnlock(state->def);
}
Ejemplo n.º 8
0
static void
cachemgrStateFree(cachemgrStateData * mgr)
{
    safe_free(mgr->action);
    safe_free(mgr->user_name);
    safe_free(mgr->passwd);
    storeUnlockObject(mgr->entry);
    xfree(mgr);
}
Ejemplo n.º 9
0
static void
waisStateFree(int fdnotused, void *data)
{
    WaisStateData *waisState = data;
    if (waisState == NULL)
	return;
    storeUnlockObject(waisState->entry);
    requestUnlink(waisState->request);
    cbdataFree(waisState);
}
Ejemplo n.º 10
0
static void
asStateFree(void *data)
{
    ASState *asState = data;
    debug(53, 3) ("asStateFree: %s\n", storeUrl(asState->entry));
    storeClientUnregister(asState->sc, asState->entry, asState);
    storeUnlockObject(asState->entry);
    requestUnlink(asState->request);
    cbdataFree(asState);
}
Ejemplo n.º 11
0
static void
netdbExchangeDone(void *data)
{
    netdbExchangeState *ex = data;
    debug(38, 3) ("netdbExchangeDone: %s\n", storeUrl(ex->e));
    requestUnlink(ex->r);
    storeClientUnregister(ex->sc, ex->e, ex);
    storeUnlockObject(ex->e);
    cbdataUnlock(ex->p);
    cbdataFree(ex);
}
Ejemplo n.º 12
0
static void
errorMapFetchComplete(ErrorMapState * state)
{
    storeClientUnregister(state->sc, state->e, state);
    state->sc = NULL;
    storeUnlockObject(state->e);
    state->e = NULL;
    requestUnlink(state->req);
    state->req = NULL;
    cbdataUnlock(state->callback_data);
    state->callback_data = NULL;
    cbdataFree(state);
}
Ejemplo n.º 13
0
static void
gopherStateFree(int fdnotused, void *data)
{
    GopherStateData *gopherState = data;
    if (gopherState == NULL)
	return;
    if (gopherState->entry) {
	storeUnlockObject(gopherState->entry);
    }
    memFree(gopherState->buf, MEM_4K_BUF);
    gopherState->buf = NULL;
    cbdataFree(gopherState);
}
Ejemplo n.º 14
0
static void
peerMonitorCompleted(PeerMonitor * pm)
{
    int state = PEER_ALIVE;
    peer *p = pm->peer;
    storeClientUnregister(pm->running.sc, pm->running.e, pm);
    storeUnlockObject(pm->running.e);
    requestUnlink(pm->running.req);
    memFree(pm->running.buf, MEM_4K_BUF);
    if (pm->running.timeout_set) {
	eventDelete(peerMonitorTimeout, pm);
	pm->running.timeout_set = 0;
    }
    if (!cbdataValid(pm->peer)) {
	cbdataFree(pm);
	return;
    }
    /* Figure out if the response was OK or not */
    if (pm->running.status != HTTP_OK) {
	debug(DBG, 1) ("peerMonitor %s: Failed, status != 200 (%d)\n",
	    p->name, pm->running.status);
	state = PEER_DEAD;
    } else if (pm->running.size < p->monitor.min) {
	debug(DBG, 1) ("peerMonitor %s: Failed, reply size %d < min %d\n",
	    p->name, pm->running.size, p->monitor.min);
	state = PEER_DEAD;
    } else if (pm->running.size > p->monitor.max && p->monitor.max > 0) {
	debug(DBG, 1) ("peerMonitor %s: Failed, reply size %d > max %d\n",
	    p->name, pm->running.size, p->monitor.max);
	state = PEER_DEAD;
    } else {
	debug(DBG, 2) ("peerMonitor %s: OK\n", p->name);
    }
    p->monitor.state = state;
    if (state != p->stats.logged_state) {
	switch (state) {
	case PEER_ALIVE:
	    debug(DBG, 1) ("Detected REVIVED %s: %s\n",
		neighborTypeStr(p), p->name);
	    peerClearRR();
	    break;
	case PEER_DEAD:
	    debug(DBG, 1) ("Detected DEAD %s: %s\n",
		neighborTypeStr(p), p->name);
	    break;
	}
	p->stats.logged_state = state;
    }
    memset(&pm->running, 0, sizeof(pm->running));
    eventAdd(pm->name, peerMonitorRequest, pm, (double) (pm->last_probe + pm->peer->monitor.interval - current_dtime), 1);
}
Ejemplo n.º 15
0
static void
peerSelectStateFree(ps_state * psstate)
{
	if (psstate->acl_checklist)
	{
		debug(44, 1) ("calling aclChecklistFree() from peerSelectStateFree\n");
		aclChecklistFree(psstate->acl_checklist);
	}
	requestUnlink(psstate->request);
	psstate->request = NULL;
	if (psstate->entry)
	{
		assert(psstate->entry->ping_status != PING_WAITING);
		storeUnlockObject(psstate->entry);
		psstate->entry = NULL;
	}
	cbdataFree(psstate);
}
Ejemplo n.º 16
0
/*
 * Function:  errorAppendEntry
 *
 * Arguments: err - This object is destroyed after use in this function.
 *
 * Abstract:  This function generates a error page from the info contained
 *            by 'err' and then stores the text in the specified store
 *            entry.  This function should only be called by ``server
 *            side routines'' which need to communicate errors to the
 *            client side.  It should also be called from client_side.c
 *            because we now support persistent connections, and
 *            cannot assume that we can immediately write to the socket
 *            for an error.
 */
void
errorAppendEntry(StoreEntry * entry, ErrorState * err)
{
    HttpReply *rep;
    MemObject *mem = entry->mem_obj;
    assert(mem != NULL);
    assert(mem->inmem_hi == 0);
    if (entry->store_status != STORE_PENDING) {
	/*
	 * If the entry is not STORE_PENDING, then no clients
	 * care about it, and we don't need to generate an
	 * error message
	 */
	assert(EBIT_TEST(entry->flags, ENTRY_ABORTED));
	assert(mem->nclients == 0);
	errorStateFree(err);
	return;
    }
    if (err->page_id == TCP_RESET) {
	if (err->request) {
	    debug(4, 2) ("RSTing this reply\n");
	    err->request->flags.reset_tcp = 1;
	}
    }
    storeLockObject(entry);
    storeBuffer(entry);
    rep = errorBuildReply(err);
    /* Add authentication header */
    /* TODO: alter errorstate to be accel on|off aware. The 0 on the next line
     * depends on authenticate behaviour: all schemes to date send no extra data
     * on 407/401 responses, and do not check the accel state on 401/407 responses 
     */
    authenticateFixHeader(rep, err->auth_user_request, err->request, 0, 1);
    httpReplySwapOut(rep, entry);
    httpReplyAbsorb(mem->reply, rep);
    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
    storeBufferFlush(entry);
    storeComplete(entry);
    storeNegativeCache(entry);
    storeReleaseRequest(entry);
    storeUnlockObject(entry);
    errorStateFree(err);
}
Ejemplo n.º 17
0
/*
 * This routine hasn't been optimised to take advantage of the
 * passed sc. Yet.
 */
int
storeClientUnregister(store_client * sc, StoreEntry * e, void *owner)
{
    MemObject *mem = e->mem_obj;
    if (sc == NULL)
	return 0;
    debug(20, 3) ("storeClientUnregister: called for '%s'\n", storeKeyText(e->hash.key));
#if STORE_CLIENT_LIST_DEBUG
    assert(sc == storeClientListSearch(e->mem_obj, owner));
#endif
    assert(sc->entry == e);
    if (mem->clients.head == NULL)
	return 0;
    dlinkDelete(&sc->node, &mem->clients);
    mem->nclients--;
    if (e->store_status == STORE_OK && e->swap_status != SWAPOUT_DONE)
	storeSwapOut(e);
    if (sc->swapin_sio) {
	storeClose(sc->swapin_sio);
	cbdataUnlock(sc->swapin_sio);
	sc->swapin_sio = NULL;
	statCounter.swap.ins++;
    }
    if (NULL != sc->new_callback) {
	/* callback with ssize = -1 to indicate unexpected termination */
	debug(20, 3) ("storeClientUnregister: store_client for %s has a callback\n",
	    mem->url);
	storeClientCallback(sc, -1);
    }
    stmemNodeUnref(&sc->node_ref);
#if DELAY_POOLS
    delayUnregisterDelayIdPtr(&sc->delay_id);
#endif
    storeSwapOutMaintainMemObject(e);
    if (mem->nclients == 0)
	CheckQuickAbort(e);
    storeUnlockObject(sc->entry);
    sc->entry = NULL;
    cbdataFree(sc);
    return 1;
}
Ejemplo n.º 18
0
/* finishes swap out sequence for the digest; schedules next rewrite */
static void
storeDigestRewriteFinish(StoreEntry * e)
{
    assert(sd_state.rewrite_lock && e == sd_state.rewrite_lock->data);
    storeComplete(e);
    storeTimestampsSet(e);
    debug(71, 2) ("storeDigestRewriteFinish: digest expires at %ld (%+d)\n",
	(long int) e->expires, (int) (e->expires - squid_curtime));
    /* is this the write order? @?@ */
    requestUnlink(e->mem_obj->request);
    e->mem_obj->request = NULL;
    storeUnlockObject(e);
    cbdataFree(sd_state.rewrite_lock);
    e = NULL;
    sd_state.rewrite_lock = NULL;
    sd_state.rewrite_count++;
    eventAdd("storeDigestRewriteStart", storeDigestRewriteStart, NULL, (double)
	Config.digest.rewrite_period, 1);
    /* resume pending Rebuild if any */
    if (sd_state.rebuild_lock)
	storeDigestRebuildResume();
}
Ejemplo n.º 19
0
static void
storeUpdateCopy(void *data, char *buf, ssize_t size)
{
    StoreUpdateState *state = data;

    if (EBIT_TEST(state->newentry->flags, ENTRY_ABORTED)) {
	debug(20, 1) ("storeUpdateCopy: Aborted at %d (%d)\n", (int) state->offset, (int) size);
	/* the abort callback deals with the needed cleanup */
	return;
    }
    if (EBIT_TEST(state->newentry->flags, KEY_PRIVATE) && state->newentry->mem_obj->nclients == 0) {
	debug(20, 2) ("storeUpdateCopy: Gone stale with no clients, skip copying of the rest\n");
	storeUpdateDone(state);
	return;
    }
    if (size < 0) {
	debug(20, 1) ("storeUpdateCopy: Error at %d (%d)\n", (int) state->offset, (int) size);
	storeUpdateDone(state);
	return;
    }
    if (size > 0) {
	storeAppend(state->newentry, buf, size);
	if (EBIT_TEST(state->newentry->flags, ENTRY_ABORTED)) {
	    debug(20, 1) ("storeUpdateCopy: Aborted on write at %d (%d)\n", (int) state->offset, (int) size);
	    return;
	}
	state->offset += size;
	storeClientCopy(state->sc, state->oldentry, state->offset, state->offset, sizeof(state->buf), state->buf, storeUpdateCopy, state);
	return;
    } else {
	storeComplete(state->newentry);
	storeUnlockObject(state->newentry);
	state->newentry = NULL;
	storeUpdateDone(state);
    }
}
Ejemplo n.º 20
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);
}
Ejemplo n.º 21
0
static void
urnHandleReply(void *data, char *buf, ssize_t size)
{
    UrnState *urnState = data;
    StoreEntry *e = urnState->entry;
    StoreEntry *urlres_e = urnState->urlres_e;
    char *s = NULL;
    size_t k;
    HttpReply *rep;
    url_entry *urls;
    url_entry *u;
    url_entry *min_u;
    MemBuf mb;
    ErrorState *err;
    int i;
    int urlcnt = 0;
    http_version_t version;

    debug(52, 3) ("urnHandleReply: Called with size=%d.\n", (int) size);
    if (EBIT_TEST(urlres_e->flags, ENTRY_ABORTED)) {
	memFree(buf, MEM_4K_BUF);
	return;
    }
    if (size == 0) {
	memFree(buf, MEM_4K_BUF);
	return;
    } else if (size < 0) {
	memFree(buf, MEM_4K_BUF);
	return;
    }
    if (urlres_e->store_status == STORE_PENDING && size < SM_PAGE_SIZE) {
	storeClientCopy(urnState->sc, urlres_e,
	    size,
	    0,
	    SM_PAGE_SIZE,
	    buf,
	    urnHandleReply,
	    urnState);
	return;
    }
    /* we know its STORE_OK */
    k = headersEnd(buf, size);
    if (0 == k) {
	debug(52, 1) ("urnHandleReply: didn't find end-of-headers for %s\n",
	    storeUrl(e));
	return;
    }
    s = buf + k;
    assert(urlres_e->mem_obj->reply);
    httpReplyParse(urlres_e->mem_obj->reply, buf, k);
    debug(52, 3) ("mem->reply exists, code=%d.\n",
	urlres_e->mem_obj->reply->sline.status);
    if (urlres_e->mem_obj->reply->sline.status != HTTP_OK) {
	debug(52, 3) ("urnHandleReply: failed.\n");
	err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
	err->request = requestLink(urnState->request);
	err->url = xstrdup(storeUrl(e));
	errorAppendEntry(e, err);
	return;
    }
    while (xisspace(*s))
	s++;
    urls = urnParseReply(s, urnState->request->method);
    for (i = 0; NULL != urls[i].url; i++)
	urlcnt++;
    debug(53, 3) ("urnFindMinRtt: Counted %d URLs\n", i);
    if (urls == NULL) {		/* unkown URN error */
	debug(52, 3) ("urnTranslateDone: unknown URN %s\n", storeUrl(e));
	err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
	err->request = requestLink(urnState->request);
	err->url = xstrdup(storeUrl(e));
	errorAppendEntry(e, err);
	return;
    }
    min_u = urnFindMinRtt(urls, urnState->request->method, NULL);
    qsort(urls, urlcnt, sizeof(*urls), url_entry_sort);
    storeBuffer(e);
    memBufDefInit(&mb);
    memBufPrintf(&mb,
	"<TITLE>Select URL for %s</TITLE>\n"
	"<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>\n"
	"<H2>Select URL for %s</H2>\n"
	"<TABLE BORDER=\"0\" WIDTH=\"100%%\">\n", storeUrl(e), storeUrl(e));
    for (i = 0; i < urlcnt; i++) {
	u = &urls[i];
	debug(52, 3) ("URL {%s}\n", u->url);
	memBufPrintf(&mb,
	    "<TR><TD><A HREF=\"%s\">%s</A></TD>", u->url, u->url);
	if (urls[i].rtt > 0)
	    memBufPrintf(&mb,
		"<TD align=\"right\">%4d <it>ms</it></TD>", u->rtt);
	else
	    memBufPrintf(&mb, "<TD align=\"right\">Unknown</TD>");
	memBufPrintf(&mb,
	    "<TD>%s</TD></TR>\n", u->flags.cached ? "    [cached]" : " ");
    }
    memBufPrintf(&mb,
	"</TABLE>"
	"<HR noshade size=\"1px\">\n"
	"<ADDRESS>\n"
	"Generated by %s@%s\n"
	"</ADDRESS>\n",
	full_appname_string, getMyHostname());
    rep = e->mem_obj->reply;
    httpReplyReset(rep);
    httpBuildVersion(&version, 1, 0);
    httpReplySetHeaders(rep, version, HTTP_MOVED_TEMPORARILY, NULL,
	"text/html", mb.size, 0, squid_curtime);
    if (urnState->flags.force_menu) {
	debug(51, 3) ("urnHandleReply: forcing menu\n");
    } else if (min_u) {
	httpHeaderPutStr(&rep->header, HDR_LOCATION, min_u->url);
    }
    httpBodySet(&rep->body, &mb);
    httpReplySwapOut(rep, e);
    storeComplete(e);
    memFree(buf, MEM_4K_BUF);
    for (i = 0; i < urlcnt; i++) {
	safe_free(urls[i].url);
	safe_free(urls[i].host);
    }
    safe_free(urls);
    /* mb was absorbed in httpBodySet call, so we must not clean it */
    storeUnregister(urnState->sc, urlres_e, urnState);
    storeUnlockObject(urlres_e);
    storeUnlockObject(urnState->entry);
    requestUnlink(urnState->request);
    requestUnlink(urnState->urlres_r);
    cbdataFree(urnState);
}
/*handle errorEntry here*/
static int repl_send_start(clientHttpRequest *http, int *ret)
{
    debug(115, 4)("mod_customized_server_side_error_page repl_send_start\n");
	int fd= http->conn->fd;
	mod_config* cfg = cc_get_mod_param(fd,mod);
	//mod_config *cfg = ((mod_config*)(param->param));
	if(fd_table[fd].cc_run_state[mod->slot]>0)
	{
		error_page_private_data* pd = (error_page_private_data*) cc_get_mod_private_data(REQUEST_PRIVATE_DATA,http,mod);

		if(pd->OfflineTimeToLive > 0&& pd->recusive_time<2 && pd->recusive_time > 0 && cfg->customized_error_text.buf != NULL/* && pd->ResponseStatus <400 */)
		{
			debug(115,4)("customized_server_side_error_page: repl_send_start the recusive_time is: %d\n",pd->recusive_time);
			ErrorState *err;
			err_type page_id;
			int status = pd->ResponseStatus;
			switch(status)
			{
				case HTTP_BAD_REQUEST:
				case HTTP_LENGTH_REQUIRED:
				case HTTP_EXPECTATION_FAILED:
					page_id = ERR_INVALID_REQ;
					break;
				case HTTP_UNAUTHORIZED:
				case HTTP_FORBIDDEN:
				case HTTP_METHOD_NOT_ALLOWED:
				case HTTP_NOT_ACCEPTABLE:
				case HTTP_PROXY_AUTHENTICATION_REQUIRED:
				case HTTP_REQUEST_TIMEOUT:
				case HTTP_CONFLICT:
				case HTTP_GONE:
				case HTTP_PRECONDITION_FAILED:
				case HTTP_UNSUPPORTED_MEDIA_TYPE:
				case HTTP_UNPROCESSABLE_ENTITY:
				case HTTP_LOCKED:
				case HTTP_FAILED_DEPENDENCY:
					page_id = ERR_ACCESS_DENIED;
					break;
				case HTTP_NOT_FOUND :
					page_id = ERR_FTP_NOT_FOUND;
					break;
				case HTTP_REQUEST_ENTITY_TOO_LARGE:
				case HTTP_REQUEST_URI_TOO_LONG:
					page_id = ERR_TOO_BIG;
					break;
				case HTTP_INTERNAL_SERVER_ERROR:
					page_id= ERR_SOCKET_FAILURE;
					break;
				case HTTP_NOT_IMPLEMENTED:
					page_id = ERR_UNSUP_REQ;
					break;
				case HTTP_BAD_GATEWAY:
				case HTTP_GATEWAY_TIMEOUT:
					page_id = ERR_CONNECT_FAIL;
					break;
				case HTTP_SERVICE_UNAVAILABLE:
					page_id = ERR_FTP_UNAVAILABLE;
					break;
				default:
					page_id = ERR_HTTP_SPECIAL;
			}
			//	err = errorCon(page_id,


			err = errorCon(page_id,pd->ResponseStatus,http->request);

			/********************may be leak here**********************************/

			assert(err!=NULL);
			if(squid_curtime > cfg->error_page_expires)
				cfg->error_page_expires = squid_curtime + pd->OfflineTimeToLive;
			//err->request = requestLink(http->request);
			storeClientUnregister(http->sc,http->entry,http);
			http->sc = NULL;
			storeUnlockObject(http->entry);
			http->log_type = LOG_TCP_HIT;
			http->entry = clientCreateStoreEntry(http,http->request->method,null_request_flags);

			debug(115,4)("mod_customized_server_side_error_page repl_send_start: before errorAppendEntry, the err->page_id is: %d, the err->http_status is: %d , the err->type is: %d \n",err->page_id, err->http_status,err->type);
			errorAppendEntry(http->entry,err);
			/********************may be leak here**********************************/
			*ret = 1;

		}

        // add by xueye.zhao
        // 2013-4-18
        else if (pd->OfflineTimeToLive > 0&& pd->recusive_time<2 && pd->recusive_time > 0)
        {
            if(squid_curtime > cfg->error_page_expires)
                cfg->error_page_expires = squid_curtime + pd->OfflineTimeToLive;

            HttpReply *rep = httpReplyCreate();
            http->entry = clientCreateStoreEntry(http, http->request->method, http->request->flags);
            http->log_type = LOG_TCP_MISS;
            storeReleaseRequest(http->entry);
            httpRedirectReply(rep, cfg->ResponseStatus, cfg->location);
            httpReplySwapOut(rep, http->entry);
            storeComplete(http->entry);
            *ret = 1;

            return *ret; 
        }
        // end add
    }
	return *ret;	
}
Ejemplo n.º 23
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);
    }
}