예제 #1
0
void
netdbBinaryExchange(StoreEntry * s)
{
    http_reply *reply = s->mem_obj->reply;
#if USE_ICMP
    netdbEntry *n;
    int i;
    int j;
    int rec_sz;
    char *buf;
    struct in_addr addr;
    storeBuffer(s);
    httpReplyReset(reply);
    httpReplySetHeaders(reply, HTTP_OK, "OK", NULL, -1, squid_curtime, -1);
    httpReplySwapOut(reply, s);
    rec_sz = 0;
    rec_sz += 1 + sizeof(addr.s_addr);
    rec_sz += 1 + sizeof(int);
    rec_sz += 1 + sizeof(int);
    buf = memAllocate(MEM_4K_BUF);
    i = 0;
    hash_first(addr_table);
    while ((n = (netdbEntry *) hash_next(addr_table))) {
        if (0.0 == n->rtt)
            continue;
        if (n->rtt > 60000)	/* RTT > 1 MIN probably bogus */
            continue;
        if (!safe_inet_addr(n->network, &addr))
            continue;
        buf[i++] = (char) NETDB_EX_NETWORK;
        xmemcpy(&buf[i], &addr.s_addr, sizeof(addr.s_addr));
        i += sizeof(addr.s_addr);
        buf[i++] = (char) NETDB_EX_RTT;
        j = htonl((int) (n->rtt * 1000));
        xmemcpy(&buf[i], &j, sizeof(int));
        i += sizeof(int);
        buf[i++] = (char) NETDB_EX_HOPS;
        j = htonl((int) (n->hops * 1000));
        xmemcpy(&buf[i], &j, sizeof(int));
        i += sizeof(int);
        if (i + rec_sz > 4096) {
            storeAppend(s, buf, i);
            i = 0;
        }
    }
    if (i > 0) {
        storeAppend(s, buf, i);
        i = 0;
    }
    assert(0 == i);
    storeBufferFlush(s);
    memFree(buf, MEM_4K_BUF);
#else
    httpReplyReset(reply);
    httpReplySetHeaders(reply, HTTP_BAD_REQUEST, "Bad Request", NULL, -1, -1, -1);
    httpReplySwapOut(reply, s);
    storeAppendPrintf(s, "NETDB support not compiled into this Squid cache.\n");
#endif
    storeComplete(s);
}
예제 #2
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);
}
/* create MIME Header for Gopher Data */
static void
gopherMimeCreate(GopherStateData * gopherState)
{
    StoreEntry *e = gopherState->entry;
    HttpReply *reply = e->mem_obj->reply;
    http_version_t version;
    const char *mime_type = NULL;
    const char *mime_enc = NULL;

    switch (gopherState->type_id) {
    case GOPHER_DIRECTORY:
    case GOPHER_INDEX:
    case GOPHER_HTML:
    case GOPHER_WWW:
    case GOPHER_CSO:
	mime_type = "text/html";
	break;
    case GOPHER_GIF:
    case GOPHER_IMAGE:
    case GOPHER_PLUS_IMAGE:
	mime_type = "image/gif";
	break;
    case GOPHER_SOUND:
    case GOPHER_PLUS_SOUND:
	mime_type = "audio/basic";
	break;
    case GOPHER_PLUS_MOVIE:
	mime_type = "video/mpeg";
	break;
    case GOPHER_MACBINHEX:
	mime_type = "application/macbinary";
	break;
    case GOPHER_DOSBIN:
    case GOPHER_UUENCODED:
    case GOPHER_BIN:
    case GOPHER_FILE:
    default:
	/* Rightnow We have no idea what it is. */
	mime_type = mimeGetContentType(gopherState->request);
	mime_enc = mimeGetContentEncoding(gopherState->request);
	break;
    }

    storeBuffer(e);
    httpReplyReset(reply);
    EBIT_CLR(gopherState->entry->flags, ENTRY_FWD_HDR_WAIT);
    httpBuildVersion(&version, 1, 0);
    httpReplySetHeaders(reply, version, HTTP_OK, "Gatewaying", mime_type, -1, -1, -1);
    if (mime_enc)
	httpHeaderPutStr(&reply->header, HDR_CONTENT_ENCODING, mime_enc);
    httpReplySwapOut(reply, e);
    reply->hdr_sz = e->mem_obj->inmem_hi;
    storeTimestampsSet(e);
    if (EBIT_TEST(e->flags, ENTRY_CACHABLE)) {
	storeSetPublicKey(e);
    } else {
	storeRelease(e);
    }
}
static void
whoisReadReply(int fd, void *data)
{
    WhoisState *p = data;
    StoreEntry *entry = p->entry;
    char *buf = memAllocate(MEM_4K_BUF);
    MemObject *mem = entry->mem_obj;
    int len;
    statCounter.syscalls.sock.reads++;
    len = FD_READ_METHOD(fd, buf, 4095);
    buf[len] = '\0';
    debug(75, 3) ("whoisReadReply: FD %d read %d bytes\n", fd, len);
    debug(75, 5) ("{%s}\n", buf);
    if (len > 0) {
	if (0 == mem->inmem_hi) {
	    http_reply *reply = mem->reply;
	    http_version_t version;
	    storeBuffer(entry);
	    httpBuildVersion(&version, 1, 0);
	    httpReplySetHeaders(reply, version, HTTP_OK, "Gatewaying", "text/plain", -1, -1, -2);
	    httpReplySwapOut(reply, entry);
	}
	fd_bytes(fd, len, FD_READ);
	kb_incr(&statCounter.server.all.kbytes_in, len);
	kb_incr(&statCounter.server.http.kbytes_in, len);
	storeAppend(entry, buf, len);
	storeBufferFlush(entry);
	commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read);
    } else if (len < 0) {
	debug(50, 2) ("whoisReadReply: FD %d: read failure: %s.\n",
	    fd, xstrerror());
	if (ignoreErrno(errno)) {
	    commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read);
	} else {
	    ErrorState *err;
	    err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, p->fwd->request);
	    err->xerrno = errno;
	    fwdFail(p->fwd, err);
	    comm_close(fd);
	}
    } else {
	storeTimestampsSet(entry);
	storeBufferFlush(entry);
	if (!EBIT_TEST(entry->flags, RELEASE_REQUEST))
	    storeSetPublicKey(entry);
	fwdComplete(p->fwd);
	debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry));
	comm_close(fd);
    }
    memFree(buf, MEM_4K_BUF);
}
예제 #5
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);
}
예제 #6
0
static void
storeDigestRewriteResume(void)
{
    StoreEntry *e;

    assert(sd_state.rewrite_lock);
    assert(!sd_state.rebuild_lock);
    e = sd_state.rewrite_lock->data;
    sd_state.rewrite_offset = 0;
    EBIT_SET(e->flags, ENTRY_SPECIAL);
    /* setting public key will purge old digest entry if any */
    storeSetPublicKey(e);
    /* fake reply */
    httpReplyReset(e->mem_obj->reply);
    httpReplySetHeaders(e->mem_obj->reply, 200, "Cache Digest OK", "application/cache-digest", store_digest->mask_size + sizeof(sd_state.cblock), squid_curtime, squid_curtime + Config.digest.rewrite_period);
    debug(71, 3) ("storeDigestRewriteResume: entry expires on %ld (%+d)\n",
	(long int) e->mem_obj->reply->expires, (int) (e->mem_obj->reply->expires - squid_curtime));
    storeBuffer(e);
    httpReplySwapOut(e->mem_obj->reply, e);
    e->mem_obj->reply->hdr_sz = e->mem_obj->inmem_hi;
    storeDigestCBlockSwapOut(e);
    storeBufferFlush(e);
    eventAdd("storeDigestSwapOutStep", storeDigestSwapOutStep, sd_state.rewrite_lock, 0.0, 1);
}
예제 #7
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);
}
예제 #8
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;
}
예제 #9
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);
}
static int process_miss_in_error_page(clientHttpRequest* http ,int *ret)
{
    debug(115, 4)("mod_customized_server_side_error_page process_miss_in_error_page\n");
	int fd = http->conn->fd;
	if(fd_table[fd].cc_run_state[mod->slot]>0)
	{
		mod_config* cfg = cc_get_mod_param(fd,mod);
		if(squid_curtime < cfg->error_page_expires )
		{
			ErrorState* err = NULL;
			/**********************************/
			err_type page_id;
            int status = cfg->ResponseStatus;
            
            // add by xueye.zhao
            // 2013-4-18

            if (is_http_move_status(status))
            {
                HttpReply *rep = httpReplyCreate();
                http->entry = clientCreateStoreEntry(http, http->request->method, http->request->flags);
                http->log_type = LOG_TCP_HIT;
                storeReleaseRequest(http->entry);
                httpRedirectReply(rep, cfg->ResponseStatus, cfg->location);
                httpReplySwapOut(rep, http->entry);
                storeComplete(http->entry);

                *ret = 1;
                return *ret;
            }

            //end add

			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;
			}
			/**********************************/
			debug(115, 5)("mod_customized_server_side_error_page: cc_error_page running, don't back source server\n");
			http->al.http.code = HTTP_FORBIDDEN;
			err = errorCon(page_id, cfg->ResponseStatus,http->request);
//			err->request = requestLink(http->request);
			err->src_addr = http->conn->peer.sin_addr;
			http->log_type = LOG_TCP_DENIED;
			http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags);
			errorAppendEntry(http->entry, err);
			*ret =1;
		}
	}
	return *ret;
		
}
/*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;	
}
void
netdbDump(StoreEntry * sentry)
{
#if USE_ICMP
    netdbEntry *n;
    netdbEntry **list;
    net_db_name *x;
    int k;
    int i;
    int j;
    net_db_peer *p;
    storeAppendPrintf(sentry, "Network DB Statistics:\n");
    storeAppendPrintf(sentry, "%-16.16s %9s %7s %5s %s\n",
	"Network",
	"recv/sent",
	"RTT",
	"Hops",
	"Hostnames");
    list = xcalloc(memInUse(MEM_NETDBENTRY), sizeof(netdbEntry *));
    i = 0;
    hash_first(addr_table);
    while ((n = (netdbEntry *) hash_next(addr_table)))
	*(list + i++) = n;
    if (i != memInUse(MEM_NETDBENTRY))
	debug(38, 0) ("WARNING: netdb_addrs count off, found %d, expected %d\n",
	    i, memInUse(MEM_NETDBENTRY));
    qsort((char *) list,
	i,
	sizeof(netdbEntry *),
	sortByRtt);
    for (k = 0; k < i; k++) {
	n = *(list + k);
	storeAppendPrintf(sentry, "%-16.16s %4d/%4d %7.1f %5.1f",
	    n->network,
	    n->pings_recv,
	    n->pings_sent,
	    n->rtt,
	    n->hops);
	for (x = n->hosts; x; x = x->next)
	    storeAppendPrintf(sentry, " %s", hashKeyStr(&x->hash));
	storeAppendPrintf(sentry, "\n");
	p = n->peers;
	for (j = 0; j < n->n_peers; j++, p++) {
	    storeAppendPrintf(sentry, "    %-22.22s %7.1f %5.1f\n",
		p->peername,
		p->rtt,
		p->hops);
	}
    }
    xfree(list);
#else
    http_reply *reply = sentry->mem_obj->reply;
    http_version_t version;
    httpReplyReset(reply);
    httpBuildVersion(&version, 1, 0);
    httpReplySetHeaders(reply, version, HTTP_BAD_REQUEST, "Bad Request",
	NULL, -1, squid_curtime, -2);
    httpReplySwapOut(reply, sentry);
    storeAppendPrintf(sentry,
	"NETDB support not compiled into this Squid cache.\n");
#endif
}