/* 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); }
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); } }
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); }
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); }
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); }
static void free_refreshCheckState(void *data) { refreshCheckState *state = data; storeUnlockObject(state->entry); cbdataUnlock(state->callback_data); cbdataUnlock(state->def); }
static void cachemgrStateFree(cachemgrStateData * mgr) { safe_free(mgr->action); safe_free(mgr->user_name); safe_free(mgr->passwd); storeUnlockObject(mgr->entry); xfree(mgr); }
static void waisStateFree(int fdnotused, void *data) { WaisStateData *waisState = data; if (waisState == NULL) return; storeUnlockObject(waisState->entry); requestUnlink(waisState->request); cbdataFree(waisState); }
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); }
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); }
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); }
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); }
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); }
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); }
/* * 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); }
/* * 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; }
/* 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(); }
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); } }
/* 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); }
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; }
/* 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); } }