/* 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"); storeClientUnregister(fetch->old_sc, fetch->old_entry, fetch); storeReleaseRequest(fetch->old_entry); storeUnlockObject(fetch->old_entry); fetch->old_entry = NULL; } /* update global stats */ kb_incr(&statCounter.cd.kbytes_sent, (size_t) fetch->sent.bytes); kb_incr(&statCounter.cd.kbytes_recv, (size_t) fetch->recv.bytes); statCounter.cd.msgs_sent += fetch->sent.msg; statCounter.cd.msgs_recv += fetch->recv.msg; /* unlock everything */ storeClientUnregister(fetch->sc, 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 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 storeUpdateDone(StoreUpdateState * state) { if (state->sc) { store_client *sc = state->sc; state->sc = NULL; storeClientUnregister(sc, state->oldentry, state); } cbdataFree(state); }
static void peerMonitorTimeout(void *data) { PeerMonitor *pm = data; store_client *sc = pm->running.sc; pm->running.status = HTTP_REQUEST_TIMEOUT; pm->running.sc = NULL; pm->running.timeout_set = 0; /* This will invoke peerMonitorFetchReplyHeaders which finishes things up */ storeClientUnregister(sc, pm->running.e, pm); }
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 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 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); } }
/* 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: %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); 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"); 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, 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->sc, 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->sc, fetch->entry, size, 0, SM_PAGE_SIZE, buf, peerDigestFetchReply, fetch); } }
/*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 */ 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); }