📄 forward.c
字号:
/* * $Id: forward.c,v 1.54.2.6 1999/07/07 01:52:50 wessels Exp $ * * DEBUG: section 17 Request Forwarding * AUTHOR: Duane Wessels * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from the * Internet community. Development is led by Duane Wessels of the * National Laboratory for Applied Network Research and funded by the * National Science Foundation. Squid is Copyrighted (C) 1998 by * Duane Wessels and the University of California San Diego. Please * see the COPYRIGHT file for full details. Squid incorporates * software developed and/or copyrighted by other sources. Please see * the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"static PSC fwdStartComplete;static void fwdDispatch(FwdState *);static void fwdConnectStart(void *); /* should be same as EVH */static void fwdStateFree(FwdState * fwdState);static PF fwdConnectTimeout;static PF fwdServerClosed;static CNCB fwdConnectDone;static int fwdCheckRetry(FwdState * fwdState);static int fwdReforward(FwdState *);static void fwdStartFail(FwdState *);static void fwdLogReplyStatus(int tries, http_status status);static OBJH fwdStats;static STABH fwdAbort;#define MAX_FWD_STATS_IDX 9static int FwdReplyCodes[MAX_FWD_STATS_IDX + 1][HTTP_INVALID_HEADER + 1];static voidfwdServerFree(FwdServer * fs){ if (fs->peer) cbdataUnlock(fs->peer); memFree(fs, MEM_FWD_SERVER);}static voidfwdStateFree(FwdState * fwdState){ StoreEntry *e = fwdState->entry; int sfd; debug(17, 3) ("fwdStateFree: %p\n", fwdState); assert(e->mem_obj); if (e->store_status == STORE_PENDING) { if (e->mem_obj->inmem_hi == 0) { assert(fwdState->err); errorAppendEntry(e, fwdState->err); fwdState->err = NULL; } else { EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT); storeComplete(e); storeReleaseRequest(e); } } if (storePendingNClients(e) > 0) assert(!EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)); fwdServersFree(&fwdState->servers); requestUnlink(fwdState->request); fwdState->request = NULL; if (fwdState->err) errorStateFree(fwdState->err); storeUnregisterAbort(e); storeUnlockObject(e); fwdState->entry = NULL; sfd = fwdState->server_fd; if (sfd > -1) { comm_remove_close_handler(sfd, fwdServerClosed, fwdState); fwdState->server_fd = -1; debug(17, 3) ("fwdStateFree: closing FD %d\n", sfd); comm_close(sfd); } cbdataFree(fwdState);}static intfwdCheckRetry(FwdState * fwdState){ if (fwdState->entry->store_status != STORE_PENDING) return 0; if (fwdState->entry->mem_obj->inmem_hi > 0) return 0; if (fwdState->n_tries > 10) return 0; if (squid_curtime - fwdState->start > 120) return 0; if (fwdState->flags.dont_retry) return 0; if (pumpMethod(fwdState->request->method)) if (0 == pumpRestart(fwdState->request)) return 0; return 1;}static voidfwdServerClosed(int fd, void *data){ FwdState *fwdState = data; debug(17, 2) ("fwdServerClosed: FD %d %s\n", fd, storeUrl(fwdState->entry)); assert(fwdState->server_fd == fd); fwdState->server_fd = -1; if (fwdCheckRetry(fwdState)) { debug(17, 3) ("fwdServerClosed: re-forwarding (%d tries, %d secs)\n", fwdState->n_tries, (int) (squid_curtime - fwdState->start)); if (fwdState->servers->next) { /* cycle */ FwdServer *fs = fwdState->servers; FwdServer **T; fwdState->servers = fs->next; for (T = &fwdState->servers; *T; T = &(*T)->next); *T = fs; fs->next = NULL; } /* use eventAdd to break potential call sequence loops */ eventAdd("fwdConnectStart", fwdConnectStart, fwdState, 0.0, 1); } else { fwdStateFree(fwdState); }}static voidfwdConnectDone(int server_fd, int status, void *data){ FwdState *fwdState = data; static FwdState *current = NULL; FwdServer *fs = fwdState->servers; ErrorState *err; request_t *request = fwdState->request; assert(current != fwdState); current = fwdState; assert(fwdState->server_fd == server_fd); if (status == COMM_ERR_DNS) { fwdState->flags.dont_retry = 1; debug(17, 4) ("fwdConnectDone: Unknown host: %s\n", request->host); err = errorCon(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE); err->dnsserver_msg = xstrdup(dns_error_message); err->request = requestLink(request); fwdFail(fwdState, err); comm_close(server_fd); } else if (status != COMM_OK) { assert(fs); err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); err->xerrno = errno; if (fs->peer) { err->host = xstrdup(fs->peer->host); err->port = fs->peer->http_port; } else { err->host = xstrdup(request->host); err->port = request->port; } err->request = requestLink(request); fwdFail(fwdState, err); if (fs->peer) peerCheckConnectStart(fs->peer); comm_close(server_fd); } else { debug(17, 3) ("fwdConnectDone: FD %d: '%s'\n", server_fd, storeUrl(fwdState->entry)); fd_note(server_fd, storeUrl(fwdState->entry)); fd_table[server_fd].uses++; fwdDispatch(fwdState); } current = NULL;}static voidfwdConnectTimeout(int fd, void *data){ FwdState *fwdState = data; StoreEntry *entry = fwdState->entry; ErrorState *err; debug(17, 2) ("fwdConnectTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); assert(fd == fwdState->server_fd); if (entry->mem_obj->inmem_hi == 0) { err = errorCon(ERR_CONNECT_FAIL, HTTP_GATEWAY_TIMEOUT); err->request = requestLink(fwdState->request); err->xerrno = ETIMEDOUT; fwdFail(fwdState, err); } comm_close(fd);}static voidfwdConnectStart(void *data){ FwdState *fwdState = data; const char *url = storeUrl(fwdState->entry); int fd; ErrorState *err; FwdServer *fs = fwdState->servers; const char *host; unsigned short port; assert(fs); assert(fwdState->server_fd == -1); debug(17, 3) ("fwdConnectStart: %s\n", url); if (fs->peer) { host = fs->peer->host; port = fs->peer->http_port; } else { host = fwdState->request->host; port = fwdState->request->port; } hierarchyNote(&fwdState->request->hier, fs->code, host); if ((fd = pconnPop(host, port)) >= 0) { debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd); fwdState->server_fd = fd; fwdState->n_tries++; comm_add_close_handler(fd, fwdServerClosed, fwdState); fwdConnectDone(fd, COMM_OK, fwdState); return; } fd = comm_open(SOCK_STREAM, 0, Config.Addrs.tcp_outgoing, 0, COMM_NONBLOCKING, url); if (fd < 0) { debug(50, 4) ("fwdConnectStart: %s\n", xstrerror()); err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; err->request = requestLink(fwdState->request); fwdFail(fwdState, err); fwdStateFree(fwdState); return; } fwdState->server_fd = fd; fwdState->n_tries++; comm_add_close_handler(fd, fwdServerClosed, fwdState); commSetTimeout(fd, Config.Timeout.connect, fwdConnectTimeout, fwdState); commConnectStart(fd, host, port, fwdConnectDone, fwdState);}static voidfwdStartComplete(FwdServer * servers, void *data){ FwdState *fwdState = data; debug(17, 3) ("fwdStartComplete: %s\n", storeUrl(fwdState->entry)); if (servers != NULL) { fwdState->servers = servers; fwdConnectStart(fwdState); } else { fwdStartFail(fwdState); }}static voidfwdStartFail(FwdState * fwdState){ ErrorState *err; debug(17, 3) ("fwdStartFail: %s\n", storeUrl(fwdState->entry)); err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE); err->request = requestLink(fwdState->request); err->xerrno = errno; fwdFail(fwdState, err); fwdStateFree(fwdState);}static voidfwdDispatch(FwdState * fwdState){ peer *p; request_t *request = fwdState->request; StoreEntry *entry = fwdState->entry; debug(17, 3) ("fwdDispatch: FD %d: Fetching '%s %s'\n", fwdState->client_fd, RequestMethodStr[request->method], storeUrl(entry)); /*assert(!EBIT_TEST(entry->flags, ENTRY_DISPATCHED)); */ assert(entry->ping_status != PING_WAITING); assert(entry->lock_count); EBIT_SET(entry->flags, ENTRY_DISPATCHED); netdbPingSite(request->host); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -