Пример #1
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);
}
Пример #2
0
/*
 * Function:  errorSendComplete
 *
 * Abstract:  Called by commHandleWrite() after data has been written
 *            to the client socket.
 *
 * Note:      If there is a callback, the callback is responsible for
 *            closeing the FD, otherwise we do it ourseves.
 */
static void
errorSendComplete(int fd, char *bufnotused, size_t size, int errflag, void *data)
{
    ErrorState *err = data;
    debug(4, 3) ("errorSendComplete: FD %d, size=%ld\n", fd, (long int) size);
    if (errflag != COMM_ERR_CLOSING) {
	if (err->callback) {
	    debug(4, 3) ("errorSendComplete: callback\n");
	    err->callback(fd, err->callback_data, size);
	} else {
	    comm_close(fd);
	    debug(4, 3) ("errorSendComplete: comm_close\n");
	}
    }
    errorStateFree(err);
}
Пример #3
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);
}