示例#1
0
void
urnStart(request_t * r, StoreEntry * e)
{
    LOCAL_ARRAY(char, urlres, 4096);
    request_t *urlres_r = NULL;
    const char *t;
    char *host;
    UrnState *urnState;
    StoreEntry *urlres_e;
    ErrorState *err;
    debug(52, 3) ("urnStart: '%s'\n", storeUrl(e));
    CBDATA_INIT_TYPE(UrnState);
    urnState = cbdataAlloc(UrnState);
    urnState->entry = e;
    urnState->request = requestLink(r);
    storeLockObject(urnState->entry);
    if (strncasecmp(strBuf(r->urlpath), "menu.", 5) == 0) {
	char *new_path = xstrdup(strBuf(r->urlpath) + 5);
	urnState->flags.force_menu = 1;
	stringReset(&r->urlpath, new_path);
	xfree(new_path);
    }
    if ((t = strChr(r->urlpath, ':')) != NULL) {
	strSet(r->urlpath, t, '\0');
	host = xstrdup(strBuf(r->urlpath));
	strSet(r->urlpath, t, ':');
    } else {
	host = xstrdup(strBuf(r->urlpath));
    }
    snprintf(urlres, 4096, "http://%s/uri-res/N2L?urn:%s", host, strBuf(r->urlpath));
    safe_free(host);
    urlres_r = urlParse(METHOD_GET, urlres);
    if (urlres_r == NULL) {
	debug(52, 3) ("urnStart: Bad uri-res URL %s\n", urlres);
	err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND);
	err->url = xstrdup(urlres);
	errorAppendEntry(e, err);
	return;
    }
    httpHeaderPutStr(&urlres_r->header, HDR_ACCEPT, "text/plain");
    if ((urlres_e = storeGetPublic(urlres, METHOD_GET)) == NULL) {
	urlres_e = storeCreateEntry(urlres, urlres, null_request_flags, METHOD_GET);
	urnState->sc = storeClientListAdd(urlres_e, urnState);
	fwdStart(-1, urlres_e, urlres_r);
    } else {
	storeLockObject(urlres_e);
	urnState->sc = storeClientListAdd(urlres_e, urnState);
    }
    urnState->urlres_e = urlres_e;
    urnState->urlres_r = requestLink(urlres_r);
    storeClientCopy(urnState->sc, urlres_e,
	0,
	0,
	4096,
	memAllocate(MEM_4K_BUF),
	urnHandleReply,
	urnState);
}
示例#2
0
文件: asn.c 项目: CoolerVoid/squid
static void
asnCacheStart(int as)
{
    LOCAL_ARRAY(char, asres, 4096);
    StoreEntry *e;
    request_t *req;
    ASState *asState;
    method_t *method_get;
    method_get = urlMethodGetKnownByCode(METHOD_GET);
    asState = cbdataAlloc(ASState);
    debug(53, 3) ("asnCacheStart: AS %d\n", as);
    snprintf(asres, 4096, "whois://%s/!gAS%d", Config.as_whois_server, as);
    asState->as_number = as;
    req = urlParse(method_get, asres);
    assert(NULL != req);
    asState->request = requestLink(req);
    if ((e = storeGetPublic(asres, method_get)) == NULL) {
	e = storeCreateEntry(asres, null_request_flags, method_get);
	asState->sc = storeClientRegister(e, asState);
	fwdStart(-1, e, asState->request);
    } else {
	storeLockObject(e);
	asState->sc = storeClientRegister(e, asState);
    }
    asState->entry = e;
    asState->seen = 0;
    asState->offset = 0;
    storeClientRef(asState->sc,
	e,
	asState->seen,
	asState->offset,
	SM_PAGE_SIZE,
	asHandleReply,
	asState);
}
/* add client with fd to client list */
store_client *
storeClientRegister(StoreEntry * e, void *owner)
{
    MemObject *mem = e->mem_obj;
    store_client *sc;
    assert(mem);
    e->refcount++;
    mem->nclients++;
    sc = cbdataAlloc(store_client);
    sc->callback_data = NULL;
    sc->seen_offset = 0;
    sc->copy_offset = 0;
    sc->flags.disk_io_pending = 0;
    sc->entry = e;
    storeLockObject(sc->entry);
    sc->type = storeClientType(e);
#if STORE_CLIENT_LIST_DEBUG
    assert(!storeClientListSearch(mem, owner));
    sc->owner = owner;
#endif
    dlinkAdd(sc, &sc->node, &mem->clients);
#if DELAY_POOLS
    sc->delay_id = 0;
#endif
    return sc;
}
示例#4
0
void
peerSelect(request_t * request,
		   StoreEntry * entry,
		   PSC * callback,
		   void *callback_data)
{
	ps_state *psstate;
	if (entry)
		debug(44, 3) ("peerSelect: %s\n", storeUrl(entry));
	else
		debug(44, 3) ("peerSelect: %s\n", RequestMethods[request->method].str);
	psstate = cbdataAlloc(ps_state);
	psstate->request = requestLink(request);
	psstate->entry = entry;
	psstate->callback = callback;
	psstate->callback_data = callback_data;
	psstate->direct = DIRECT_UNKNOWN;
#if USE_CACHE_DIGESTS
	request->hier.peer_select_start = current_time;
#endif
	if (psstate->entry)
		storeLockObject(psstate->entry);
	cbdataLock(callback_data);
	peerSelectFoo(psstate);
}
示例#5
0
void
refreshCheckSubmit(StoreEntry * entry, REFRESHCHECK * callback, void *callback_data)
{
    MemBuf buf;
    const char *key;
    refresh_check_helper *def = Config.Program.refresh_check;
    refreshCheckState *state;
    dlink_node *node;
    refreshCheckState *oldstate = NULL;

    if (!def) {
	callback(callback_data, 0, NULL);
	return;
    }
    key = makeRefreshCheckRequest(entry, def->format);
    if (!key) {
	callback(callback_data, 0, NULL);
	return;
    }
    debug(84, 2) ("refreshCheckSubmit: for '%s'\n", key);

    /* Check for a pending lookup to hook into */
    for (node = def->queue.head; node; node = node->next) {
	refreshCheckState *oldstatetmp = node->data;
	if (entry == oldstatetmp->entry) {
	    oldstate = oldstatetmp;
	    break;
	}
    }

    state = cbdataAlloc(refreshCheckState);
    state->def = def;
    cbdataLock(state->def);
    state->entry = entry;
    storeLockObject(entry);
    state->callback = callback;
    state->callback_data = callback_data;
    cbdataLock(state->callback_data);
    if (oldstate) {
	/* Hook into pending lookup */
	state->queue = oldstate->queue;
	oldstate->queue = state;
    } else {
	/* No pending lookup found. Sumbit to helper */
	/* Check for queue overload */
	if (refreshCheckOverload(def)) {
	    debug(84, 1) ("refreshCheckSubmit: queue overload\n");
	    cbdataFree(state);
	    callback(callback_data, 0, "Overload");
	    return;
	}
	/* Send it off to the helper */
	memBufDefInit(&buf);
	memBufPrintf(&buf, "%s\n", key);
	helperSubmit(def->helper, buf.buf, refreshCheckHandleReply, state);
	dlinkAdd(state, &state->list, &def->queue);
	memBufClean(&buf);
    }
}
示例#6
0
static void
icapProcessHttpReplyHeader(IcapStateData * icap, const char *buf, int size)
{
    if (NULL == icap->httpState) {
	icap->httpState = cbdataAlloc(HttpStateData);
	icap->httpState->request = requestLink(icap->request);
	icap->httpState->orig_request = requestLink(icap->request);
	icap->httpState->entry = icap->respmod.entry;
	storeLockObject(icap->httpState->entry);	/* lock it */
    }
    httpProcessReplyHeader(icap->httpState, buf, size);
    if (2 == icap->httpState->reply_hdr_state)
	EBIT_CLR(icap->httpState->entry->flags, ENTRY_FWD_HDR_WAIT);
}
示例#7
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);
}
void
whoisStart(FwdState * fwd)
{
    WhoisState *p;
    int fd = fwd->server_fd;
    char *buf;
    size_t l;
    CBDATA_INIT_TYPE(WhoisState);
    p = cbdataAlloc(WhoisState);
    p->request = fwd->request;
    p->entry = fwd->entry;
    p->fwd = fwd;
    storeLockObject(p->entry);
    comm_add_close_handler(fd, whoisClose, p);
    l = strLen(p->request->urlpath) + 3;
    buf = xmalloc(l);
    snprintf(buf, l, "%s\r\n", strBuf(p->request->urlpath) + 1);
    comm_write(fd, buf, strlen(buf), NULL, p, xfree);
    commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, 0);
    commSetTimeout(fd, Config.Timeout.read, whoisTimeout, p);
}
示例#9
0
static StoreEntry *
heap_purgeNext(RemovalPurgeWalker * walker)
{
    HeapPurgeData *heap_walker = walker->_data;
    RemovalPolicy *policy = walker->_policy;
    HeapPolicyData *heap = policy->_data;
    StoreEntry *entry;
    heap_key age;
  try_again:
    if (!heap_nodes(heap->heap) > 0)
	return NULL;		/* done */
    age = heap_peepminkey(heap->heap);
    entry = heap_extractmin(heap->heap);
    if (storeEntryLocked(entry)) {
	storeLockObject(entry);
	linklistPush(&heap_walker->locked_entries, entry);
	goto try_again;
    }
    heap_walker->min_age = age;
    SET_POLICY_NODE(entry, NULL);
    return entry;
}
示例#10
0
/* ask store for a digest */
static void
peerDigestRequest(PeerDigest * pd)
{
    peer *p = pd->peer;
    StoreEntry *e, *old_e;
    char *url;
    const cache_key *key;
    request_t *req;
    DigestFetchState *fetch = NULL;

    pd->req_result = NULL;
    pd->flags.requested = 1;

    /* compute future request components */
    if (p->digest_url)
	url = xstrdup(p->digest_url);
    else
	url = internalRemoteUri(p->host, p->http_port,
	    "/squid-internal-periodic/", StoreDigestFileName);

    key = storeKeyPublic(url, METHOD_GET);
    debug(72, 2) ("peerDigestRequest: %s key: %s\n", url, storeKeyText(key));
    req = urlParse(METHOD_GET, url);
    assert(req);

    /* add custom headers */
    assert(!req->header.len);
    httpHeaderPutStr(&req->header, HDR_ACCEPT, StoreDigestMimeStr);
    httpHeaderPutStr(&req->header, HDR_ACCEPT, "text/html");
    if (p->login)
	xstrncpy(req->login, p->login, MAX_LOGIN_SZ);
    /* create fetch state structure */
    fetch = memAllocate(MEM_DIGEST_FETCH_STATE);
    cbdataAdd(fetch, memFree, MEM_DIGEST_FETCH_STATE);
    fetch->request = requestLink(req);
    fetch->pd = pd;
    fetch->offset = 0;

    /* update timestamps */
    fetch->start_time = squid_curtime;
    pd->times.requested = squid_curtime;
    pd_last_req_time = squid_curtime;

    req->flags.cachable = 1;
    /* the rest is based on clientProcessExpired() */
    req->flags.refresh = 1;
    old_e = fetch->old_entry = storeGet(key);
    if (old_e) {
	debug(72, 5) ("peerDigestRequest: found old entry\n");
	storeLockObject(old_e);
	storeCreateMemObject(old_e, url, url);
	storeClientListAdd(old_e, fetch);
    }
    e = fetch->entry = storeCreateEntry(url, url, req->flags, req->method);
    assert(EBIT_TEST(e->flags, KEY_PRIVATE));
    storeClientListAdd(e, fetch);
    /* set lastmod to trigger IMS request if possible */
    if (old_e)
	e->lastmod = old_e->lastmod;

    /* push towards peer cache */
    debug(72, 3) ("peerDigestRequest: forwarding to fwdStart...\n");
    fwdStart(-1, e, req);
    cbdataLock(fetch);
    cbdataLock(fetch->pd);
    storeClientCopy(e, 0, 0, 4096, memAllocate(MEM_4K_BUF),
	peerDigestFetchReply, fetch);
}
示例#11
0
void
cachemgrStart(int fd, request_t * request, StoreEntry * entry)
{
    cachemgrStateData *mgr = NULL;
    ErrorState *err = NULL;
    action_table *a;
    debug(16, 3) ("cachemgrStart: '%s'\n", storeUrl(entry));
    if ((mgr = cachemgrParseUrl(storeUrl(entry))) == NULL) {
	err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND, request);
	err->url = xstrdup(storeUrl(entry));
	errorAppendEntry(entry, err);
	entry->expires = squid_curtime;
	return;
    }
    mgr->entry = entry;
    storeLockObject(entry);
    entry->expires = squid_curtime;
    debug(16, 5) ("CACHEMGR: %s requesting '%s'\n",
	fd_table[fd].ipaddr, mgr->action);
    /* get additional info from request headers */
    cachemgrParseHeaders(mgr, request);
    /* Check password */
    if (cachemgrCheckPassword(mgr) != 0) {
	/* build error message */
	ErrorState *err;
	HttpReply *rep;
	err = errorCon(ERR_CACHE_MGR_ACCESS_DENIED, HTTP_UNAUTHORIZED, request);
	/* warn if user specified incorrect password */
	if (mgr->passwd)
	    debug(16, 1) ("CACHEMGR: %s@%s: incorrect password for '%s'\n",
		mgr->user_name ? mgr->user_name : "<unknown>",
		fd_table[fd].ipaddr, mgr->action);
	else
	    debug(16, 1) ("CACHEMGR: %s@%s: password needed for '%s'\n",
		mgr->user_name ? mgr->user_name : "<unknown>",
		fd_table[fd].ipaddr, mgr->action);
	rep = errorBuildReply(err);
	errorStateFree(err);
	/*
	 * add Authenticate header, use 'action' as a realm because
	 * password depends on action
	 */
	httpHeaderPutAuth(&rep->header, "Basic", mgr->action);
	/* store the reply */
	httpReplySwapOut(rep, entry);
	entry->expires = squid_curtime;
	storeComplete(entry);
	cachemgrStateFree(mgr);
	return;
    }
    debug(16, 1) ("CACHEMGR: %s@%s requesting '%s'\n",
	mgr->user_name ? mgr->user_name : "<unknown>",
	fd_table[fd].ipaddr, mgr->action);
    /* retrieve object requested */
    a = cachemgrFindAction(mgr->action);
    assert(a != NULL);
    storeBuffer(entry);
    {
	HttpReply *rep = entry->mem_obj->reply;
	/* prove there are no previous reply headers around */
	assert(0 == rep->sline.status);
	httpReplySetHeaders(rep, HTTP_OK, NULL, "text/plain", -1, -1, squid_curtime);
	httpReplySwapOut(rep, entry);
    }
    a->handler(entry);
    storeBufferFlush(entry);
    if (a->flags.atomic)
	storeComplete(entry);
    cachemgrStateFree(mgr);
}
示例#12
0
IcapStateData *
icapRespModStart(icap_service_t type, request_t * request, StoreEntry * entry,
    http_state_flags http_flags)
{
    IcapStateData *icap = NULL;
    CNCB *theCallback = NULL;
    icap_service *service = NULL;

    debug(81, 3) ("icapRespModStart: type=%d\n", (int) type);
    assert(type >= 0 && type < ICAP_SERVICE_MAX);

    service = icapService(type, request);
    if (!service) {
	debug(81, 3) ("icapRespModStart: no service found\n");
	return NULL;		/* no service found */
    }
    if (service->unreachable) {
	if (service->bypass) {
	    debug(81,
		5)
		("icapRespModStart: BYPASS because service unreachable: %s\n",
		service->uri);
	    return NULL;
	} else {
	    debug(81,
		5)
		("icapRespModStart: ERROR  because service unreachable: %s\n",
		service->uri);
	    return (IcapStateData *) - 1;
	}
    }
    switch (type) {
	/* TODO: When we support more than ICAP_SERVICE_RESPMOD_PRECACHE, we needs to change
	 * this switch, because callbacks isn't keep */
    case ICAP_SERVICE_RESPMOD_PRECACHE:
	theCallback = icapConnectOver;
	break;
    default:
	fatalf("icapRespModStart: unsupported service type '%s'\n",
	    icap_service_type_str[type]);
	break;
    }

    icap = icapAllocate();
    if (!icap) {
	debug(81, 3) ("icapRespModStart: icapAllocate() failed\n");
	return NULL;
    }
    icap->request = requestLink(request);
    icap->respmod.entry = entry;
    if (entry)
	storeLockObject(entry);
    icap->http_flags = http_flags;
    memBufDefInit(&icap->respmod.buffer);
    memBufDefInit(&icap->chunk_buf);

    icap->current_service = service;
    icap->preview_size = service->preview;

    /* 
     * Don't create socket to the icap server now, but only for the first
     * packet receive from the http server. This will resolve all timeout
     * between the web server and icap server.
     */
    debug(81, 3) ("icapRespModStart: setting connect_requested to 0\n");
    icap->flags.connect_requested = 0;

    /*
     * make a copy the HTTP response that we send to the ICAP server in
     * case it turns out to be a 204
     */
#ifdef SUPPORT_ICAP_204
    icap->flags.copy_response = 1;
#elif ICAP_PREVIEW
    if(preview_size < 0 || !Config.icapcfg.preview_enable)
	 icap->flags.copy_response = 0;
    else
	 icap->flags.copy_response = 1;
#else
    icap->flags.copy_response = 0;
#endif
    
    statCounter.icap.all.requests++;
    debug(81, 3) ("icapRespModStart: returning %p\n", icap);
    return icap;
}
示例#13
0
void
storeUpdate(StoreEntry * entry, request_t * request)
{
    StoreUpdateState *state;
    request_flags flags = null_request_flags;
    const char *vary;

    if (!request)
	request = entry->mem_obj->request;

    if (EBIT_TEST(entry->flags, KEY_PRIVATE))
	return;			/* Nothing to do here... */

    if (!Config.onoff.update_headers)
	return;			/* Disabled */

    CBDATA_INIT_TYPE_FREECB(StoreUpdateState, free_StoreUpdateState);

    if (entry->mem_obj)
	entry->mem_obj->refresh_timestamp = 0;
    state = cbdataAlloc(StoreUpdateState);
    state->oldentry = entry;
    storeLockObject(state->oldentry);
    flags.cachable = 1;
    state->newentry = storeCreateEntry(storeUrl(entry), flags, entry->mem_obj->method);
    storeRegisterAbort(state->newentry, storeUpdateAbort, state);
    state->sc = storeClientRegister(state->oldentry, state);
    state->offset = entry->mem_obj->reply->hdr_sz;
    storeBuffer(state->newentry);
    httpReplySwapOut(httpReplyClone(entry->mem_obj->reply), state->newentry);
    state->newentry->timestamp = entry->timestamp;
    state->newentry->lastref = entry->lastref;
    state->newentry->expires = entry->expires;
    state->newentry->lastmod = entry->lastmod;
    state->newentry->refcount = entry->refcount;
    if (request) {
	state->newentry->mem_obj->request = requestLink(request);
	vary = httpMakeVaryMark(request, state->newentry->mem_obj->reply);
	if (vary) {
	    state->newentry->mem_obj->vary_headers = xstrdup(vary);
	    if (strBuf(request->vary_encoding))
		state->newentry->mem_obj->vary_encoding = xstrdup(strBuf(request->vary_encoding));
	}
    } else {
	if (entry->mem_obj->vary_headers)
	    state->newentry->mem_obj->vary_headers = xstrdup(entry->mem_obj->vary_headers);
	if (entry->mem_obj->vary_encoding)
	    state->newentry->mem_obj->vary_encoding = xstrdup(entry->mem_obj->vary_encoding);
    }
    storeSetPublicKey(state->newentry);
    storeBufferFlush(state->newentry);
    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
	/*
	 * the above storeBufferFlush() call could ABORT this entry,
	 * in that case, there's nothing for us to do.
	 */
	debug(20, 1) ("storeUpdate: Aborted on write\n");
	return;
    }
    storeClientCopy(state->sc, state->oldentry, state->offset, state->offset, sizeof(state->buf), state->buf, storeUpdateCopy, state);
    return;
}