📄 urn.c
字号:
/* * * $Id: urn.c,v 1.52.2.2 1999/04/09 20:01:49 wessels Exp $ * * DEBUG: section 52 URN Parsing * AUTHOR: Kostas Anagnostakis * * 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"typedef struct { StoreEntry *entry; StoreEntry *urlres_e; request_t *request; request_t *urlres_r; struct { int force_menu:1; } flags;} UrnState;typedef struct { char *url; char *host; int rtt; struct { int cached; } flags;} url_entry;static STCB urnHandleReply;static url_entry *urnParseReply(const char *inbuf, method_t);static const char *const crlf = "\r\n";static QS url_entry_sort;url_entry *urnFindMinRtt(url_entry * urls, method_t m, int *rtt_ret){ int min_rtt = 0; url_entry *u = NULL; url_entry *min_u = NULL; int i; int urlcnt = 0; debug(52, 3) ("urnFindMinRtt\n"); assert(urls != NULL); for (i = 0; NULL != urls[i].url; i++) urlcnt++; debug(53, 3) ("urnFindMinRtt: Counted %d URLs\n", i); if (1 == urlcnt) { debug(52, 3) ("urnFindMinRtt: Only one URL - return it!\n"); return urls; } for (i = 0; i < urlcnt; i++) { u = &urls[i]; debug(52, 3) ("urnFindMinRtt: %s rtt=%d\n", u->host, u->rtt); if (u->rtt == 0) continue; if (u->rtt > min_rtt && min_rtt != 0) continue; min_rtt = u->rtt; min_u = u; } if (rtt_ret) *rtt_ret = min_rtt; debug(52, 1) ("urnFindMinRtt: Returning '%s' RTT %d\n", min_u ? min_u->url : "NONE", min_rtt); return min_u;}voidurnStart(request_t * r, StoreEntry * e){ LOCAL_ARRAY(char, urlres, 4096); request_t *urlres_r = NULL; const char *t; char *host; UrnState *urnState; StoreEntry *urlres_e; ErrorState *err; debug(52, 3) ("urnStart: '%s'\n", storeUrl(e)); urnState = xcalloc(1, sizeof(UrnState)); urnState->entry = e; urnState->request = requestLink(r); cbdataAdd(urnState, cbdataXfree, 0); storeLockObject(urnState->entry); if (strncasecmp(strBuf(r->urlpath), "menu.", 5) == 0) { char *new_path = xstrdup(strBuf(r->urlpath) + 5); urnState->flags.force_menu = 1; stringReset(&r->urlpath, new_path); xfree(new_path); } if ((t = strChr(r->urlpath, ':')) != NULL) { strSet(r->urlpath, t, '\0'); host = xstrdup(strBuf(r->urlpath)); strSet(r->urlpath, t, ':'); } else { host = xstrdup(strBuf(r->urlpath)); } snprintf(urlres, 4096, "http://%s/uri-res/N2L?urn:%s", host, strBuf(r->urlpath)); safe_free(host); urlres_r = urlParse(METHOD_GET, urlres); if (urlres_r == NULL) { debug(52, 3) ("urnStart: Bad uri-res URL %s\n", urlres); err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND); err->url = xstrdup(urlres); errorAppendEntry(e, err); return; } httpHeaderPutStr(&urlres_r->header, HDR_ACCEPT, "text/plain"); if ((urlres_e = storeGetPublic(urlres, METHOD_GET)) == NULL) { urlres_e = storeCreateEntry(urlres, urlres, null_request_flags, METHOD_GET); storeClientListAdd(urlres_e, urnState); fwdStart(-1, urlres_e, urlres_r, no_addr, no_addr); } else { storeLockObject(urlres_e); storeClientListAdd(urlres_e, urnState); } urnState->urlres_e = urlres_e; urnState->urlres_r = requestLink(urlres_r); storeClientCopy(urlres_e, 0, 0, 4096, memAllocate(MEM_4K_BUF), urnHandleReply, urnState);}static inturl_entry_sort(const void *A, const void *B){ const url_entry *u1 = A; const url_entry *u2 = B; if (u2->rtt == u1->rtt) return 0; else if (0 == u1->rtt) return 1; else if (0 == u2->rtt) return -1; else return u1->rtt - u2->rtt;}static voidurnHandleReply(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; debug(52, 3) ("urnHandleReply: Called with size=%d.\n", 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(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); 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" "<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>\n" "<ADDRESS>\n" "Generated by %s@%s\n" "</ADDRESS>\n", full_appname_string, getMyHostname()); rep = e->mem_obj->reply; httpReplyReset(rep); httpReplySetHeaders(rep, 1.0, 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(urlres_e, urnState); storeUnlockObject(urlres_e); storeUnlockObject(urnState->entry); requestUnlink(urnState->request); requestUnlink(urnState->urlres_r); cbdataFree(urnState);}static url_entry *urnParseReply(const char *inbuf, method_t m){ char *buf = xstrdup(inbuf); char *token; char *url; char *host; int rtt; url_entry *list; url_entry *old; int n = 32; int i = 0; debug(52, 3) ("urnParseReply\n"); list = xcalloc(n + 1, sizeof(*list)); for (token = strtok(buf, crlf); token; token = strtok(NULL, crlf)) { debug(52, 3) ("urnParseReply: got '%s'\n", token); if (i == n) { old = list; n <<= 2; list = xcalloc(n + 1, sizeof(*list)); xmemcpy(list, old, i * sizeof(*list)); safe_free(old); } url = xstrdup(token); host = urlHostname(url); if (NULL == host) continue; rtt = netdbHostRtt(host); if (0 == rtt) { debug(52, 3) ("urnParseReply: Pinging %s\n", host); netdbPingSite(host); } list[i].url = url; list[i].host = xstrdup(host); list[i].rtt = rtt; list[i].flags.cached = storeGetPublic(url, m) ? 1 : 0; i++; } debug(52, 3) ("urnParseReply: Found %d URLs\n", i); return list;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -