📄 forward.c
字号:
* Assert that server_fd is set. This is to guarantee that fwdState * is attached to something and will be deallocated when server_fd * is closed. */ assert(fwdState->server_fd > -1); if (fwdState->servers && (p = fwdState->servers->peer)) { p->stats.fetches++; httpStart(fwdState); } else { switch (request->protocol) { case PROTO_HTTP: httpStart(fwdState); break; case PROTO_GOPHER: gopherStart(fwdState); break; case PROTO_FTP: ftpStart(fwdState); break; case PROTO_WAIS: waisStart(fwdState); break; case PROTO_CACHEOBJ: case PROTO_INTERNAL: case PROTO_URN: fatal_dump("Should never get here"); break; case PROTO_WHOIS: whoisStart(fwdState); break; default: debug(17, 1) ("fwdDispatch: Cannot retrieve '%s'\n", storeUrl(entry)); fwdFail(fwdState, errorCon(ERR_UNSUP_REQ, HTTP_BAD_REQUEST)); comm_close(fwdState->server_fd); break; } }}static intfwdReforward(FwdState * fwdState){ StoreEntry *e = fwdState->entry; FwdServer *fs = fwdState->servers; http_status s; assert(e->store_status == STORE_PENDING); assert(e->mem_obj); debug(17, 3) ("fwdReforward: %s?\n", storeUrl(e)); if (!EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) { debug(17, 3) ("fwdReforward: No, ENTRY_FWD_HDR_WAIT isn't set\n"); return 0; } if (fwdState->n_tries > 9) return 0; if (pumpMethod(fwdState->request->method)) if (0 == pumpRestart(fwdState->request)) return 0; assert(fs); fwdState->servers = fs->next; fwdServerFree(fs); if (fwdState->servers == NULL) { debug(17, 3) ("fwdReforward: No forward-servers left\n"); return 0; } s = e->mem_obj->reply->sline.status; debug(17, 3) ("fwdReforward: status %d\n", (int) s); return fwdReforwardableStatus(s);}/* PUBLIC FUNCTIONS */voidfwdServersFree(FwdServer ** FS){ FwdServer *fs; while ((fs = *FS)) { *FS = fs->next; fwdServerFree(fs); }}voidfwdStart(int fd, StoreEntry * e, request_t * r, struct in_addr client_addr, struct in_addr my_addr){ FwdState *fwdState; aclCheck_t ch; int answer; ErrorState *err; /* * client_addr == no_addr indicates this is an "internal" request * from peer_digest.c, asn.c, netdb.c, etc and should always * be allowed. yuck, I know. */ if (client_addr.s_addr != no_addr.s_addr) { /* * Check if this host is allowed to fetch MISSES from us (miss_access) */ memset(&ch, '\0', sizeof(aclCheck_t)); ch.src_addr = client_addr; ch.my_addr = my_addr; ch.request = r; answer = aclCheckFast(Config.accessList.miss, &ch); if (answer == 0) { err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN); err->request = requestLink(r); err->src_addr = client_addr; errorAppendEntry(e, err); return; } } debug(17, 3) ("fwdStart: '%s'\n", storeUrl(e)); e->mem_obj->request = requestLink(r); e->mem_obj->fd = fd; if (shutting_down) { /* more yuck */ err = errorCon(ERR_SHUTTING_DOWN, HTTP_SERVICE_UNAVAILABLE); err->request = requestLink(r); errorAppendEntry(e, err); return; } switch (r->protocol) { /* * Note, don't create fwdState for these requests */ case PROTO_INTERNAL: internalStart(r, e); return; case PROTO_CACHEOBJ: cachemgrStart(fd, r, e); return; case PROTO_URN: urnStart(r, e); return; default: break; } fwdState = memAllocate(MEM_FWD_STATE); cbdataAdd(fwdState, memFree, MEM_FWD_STATE); fwdState->entry = e; fwdState->client_fd = fd; fwdState->server_fd = -1; fwdState->request = requestLink(r); fwdState->start = squid_curtime; storeLockObject(e); EBIT_SET(e->flags, ENTRY_FWD_HDR_WAIT); storeRegisterAbort(e, fwdAbort, fwdState); peerSelect(r, e, fwdStartComplete, fwdState);}intfwdCheckDeferRead(int fd, void *data){ StoreEntry *e = data; MemObject *mem = e->mem_obj; if (mem == NULL) return 0;#if DELAY_POOLS if (fd < 0) (void) 0; else if (delayIsNoDelay(fd)) (void) 0; else if (delayMostBytesWanted(mem, 1) == 0) return 1;#endif if (EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) return 0; if (mem->inmem_hi - storeLowestMemReaderOffset(e) < READ_AHEAD_GAP) return 0; return 1;}voidfwdFail(FwdState * fwdState, ErrorState * errorState){ assert(EBIT_TEST(fwdState->entry->flags, ENTRY_FWD_HDR_WAIT)); debug(17, 3) ("fwdFail: %s \"%s\"\n\t%s\n", err_type_str[errorState->type], httpStatusString(errorState->http_status), storeUrl(fwdState->entry)); if (fwdState->err) errorStateFree(fwdState->err); fwdState->err = errorState;}/* * Called when someone else calls StoreAbort() on this entry */voidfwdAbort(void *data){ FwdState *fwdState = data; debug(17, 2) ("fwdAbort: %s\n", storeUrl(fwdState->entry)); fwdStateFree(fwdState);}/* * Frees fwdState without closing FD or generating an abort */voidfwdUnregister(int fd, FwdState * fwdState){ debug(17, 3) ("fwdUnregister: %s\n", storeUrl(fwdState->entry)); assert(fd = fwdState->server_fd); assert(fd > -1); comm_remove_close_handler(fd, fwdServerClosed, fwdState); fwdState->server_fd = -1;}/* * server-side modules call fwdComplete() when they are done * downloading an object. Then, we either 1) re-forward the * request somewhere else if needed, or 2) call storeComplete() * to finish it off */voidfwdComplete(FwdState * fwdState){ StoreEntry *e = fwdState->entry; assert(e->store_status == STORE_PENDING); debug(17, 3) ("fwdComplete: %s\n\tstatus %d\n", storeUrl(e), e->mem_obj->reply->sline.status); fwdLogReplyStatus(fwdState->n_tries, e->mem_obj->reply->sline.status); if (fwdReforward(fwdState)) { debug(17, 3) ("fwdComplete: re-forwarding %d %s\n", e->mem_obj->reply->sline.status, storeUrl(e)); if (fwdState->server_fd > -1) fwdUnregister(fwdState->server_fd, fwdState); storeEntryReset(e); fwdStartComplete(fwdState->servers, fwdState); } else { debug(17, 3) ("fwdComplete: not re-forwarding status %d\n", e->mem_obj->reply->sline.status); EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT); storeComplete(e); /* * If fwdState isn't associated with a server FD, it * won't get freed unless we do it here. */ if (fwdState->server_fd < 0) fwdStateFree(fwdState); }}voidfwdInit(void){ cachemgrRegister("forward", "Request Forwarding Statistics", fwdStats, 0, 1);}static voidfwdLogReplyStatus(int tries, http_status status){ if (status > HTTP_INVALID_HEADER) return; assert(tries); tries--; if (tries > MAX_FWD_STATS_IDX) tries = MAX_FWD_STATS_IDX; FwdReplyCodes[tries][status]++;}static voidfwdStats(StoreEntry * s){ int i; int j; storeAppendPrintf(s, "Status"); for (j = 0; j <= MAX_FWD_STATS_IDX; j++) { storeAppendPrintf(s, "\ttry#%d", j + 1); } storeAppendPrintf(s, "\n"); for (i = 0; i <= (int) HTTP_INVALID_HEADER; i++) { if (FwdReplyCodes[0][i] == 0) continue; storeAppendPrintf(s, "%3d", i); for (j = 0; j <= MAX_FWD_STATS_IDX; j++) { storeAppendPrintf(s, "\t%d", FwdReplyCodes[j][i]); } storeAppendPrintf(s, "\n"); }}intfwdReforwardableStatus(http_status s){ switch (s) { case HTTP_FORBIDDEN: case HTTP_INTERNAL_SERVER_ERROR: case HTTP_NOT_IMPLEMENTED: case HTTP_BAD_GATEWAY: case HTTP_SERVICE_UNAVAILABLE: case HTTP_GATEWAY_TIMEOUT: return 1; default: return 0; } /* NOTREACHED */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -