From 23d92c64f75d0b77afa4f96d77d122dd8dfe05a8 Mon Sep 17 00:00:00 2001 From: wessels <> Date: Sat, 6 Dec 1997 12:16:52 +0000 Subject: [PATCH] INITIAL URN SUPPORT by Kostas --- src/Makefile.in | 3 +- src/cf.data.pre | 21 + src/client_side.cc | 113 +++--- src/enums.h | 2 + src/errorpage.cc | 5 +- src/ftp.cc | 4 +- src/net_db.cc | 4 +- src/protos.h | 6 +- src/redirect.cc | 6 +- src/store.cc | 3 +- src/structs.h | 6 +- src/tools.cc | 6 +- src/typedefs.h | 3 +- src/url.cc | 26 +- src/urn.cc | 932 ++++++++++----------------------------------- 15 files changed, 329 insertions(+), 811 deletions(-) diff --git a/src/Makefile.in b/src/Makefile.in index ac305a0776..0037b1fee0 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.in,v 1.107 1997/12/05 22:01:13 wessels Exp $ +# $Id: Makefile.in,v 1.108 1997/12/06 05:16:52 wessels Exp $ # # Uncomment and customize the following to suit your needs: # @@ -127,6 +127,7 @@ OBJS = \ tools.o \ unlinkd.o \ url.o \ + urn.o \ useragent.o \ wais.o \ $(XTRA_OBJS) diff --git a/src/cf.data.pre b/src/cf.data.pre index bfee8722fe..34336ecf3c 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -313,7 +313,9 @@ DOC_START source_ping off DOC_END +#ifndef USE_URNS +#endif /* USE_URNS */ NAME: neighbor_timeout neighbour_timeout COMMENT: (seconds) DEFAULT: 2 seconds @@ -750,7 +752,9 @@ DOC_START ftp_list_width 32 DOC_END +#ifndef USE_URNS +#endif /* USE_URNS */ NAME: cache_dns_program TYPE: string DEFAULT: @DEFAULT_DNSSERVER@ @@ -761,7 +765,9 @@ DOC_START cache_dns_program @DEFAULT_DNSSERVER@ DOC_END +#ifndef USE_URNS +#endif /* USE_URNS */ NAME: dns_children TYPE: int DEFAULT: 5 @@ -1041,6 +1047,18 @@ DOC_START connect_timeout 120 seconds DOC_END +#ifdef USE_URNS +NAME: siteselect_timeout +COMMENT: time-units +TYPE: time_t +LOC: Config.Timeout.siteSelect +DEFAULT: 4 seconds +DOC_START + For URN to multiple URL's URL selection + +siteselect_timeout 4 seconds +DOC_END +#endif /* USE_URNS */ NAME: read_timeout COMMENT: time-units @@ -2073,5 +2091,8 @@ DOC_START snmp_agent_conf community public squid squid snmp_agent_conf community readwrite all all DOC_END +#ifdef USE_URNS + +#endif /* USE_URNS */ EOF diff --git a/src/client_side.cc b/src/client_side.cc index 7ab2051ba9..c2cbc5bb7b 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side.cc,v 1.173 1997/12/04 23:07:51 wessels Exp $ + * $Id: client_side.cc,v 1.174 1997/12/06 05:16:53 wessels Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -75,7 +75,6 @@ static void clientProcessExpired(void *data); static char *clientConstructProxyAuthReply(clientHttpRequest * http); static int clientCachable(clientHttpRequest * http); static int clientHierarchical(clientHttpRequest * http); -static StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, int); static int checkAccelOnly(clientHttpRequest * http) @@ -145,7 +144,7 @@ clientConstructProxyAuthReply(clientHttpRequest * http) "
\n" "Generated by %s/%s@%s\n" "
\n", - http->url, + http->uri, Config.adminEmail, getMyHostname(), Config.errHtmlText, @@ -165,7 +164,7 @@ clientConstructProxyAuthReply(clientHttpRequest * http) return buf; } -static StoreEntry * +StoreEntry * clientCreateStoreEntry(clientHttpRequest * h, method_t m, int flags) { StoreEntry *e; @@ -180,7 +179,7 @@ clientCreateStoreEntry(clientHttpRequest * h, method_t m, int flags) r->protocol = PROTO_NONE; h->request = requestLink(r); } - e = storeCreateEntry(h->url, h->log_url, flags, m); + e = storeCreateEntry(h->uri, h->log_uri, flags, m); storeClientListAdd(e, h); storeClientCopy(e, 0, 0, 4096, get_free_4k_page(), clientSendMoreData, h); return e; @@ -194,10 +193,10 @@ clientAccessCheckDone(int answer, void *data) char *redirectUrl = NULL; char *buf; ErrorState *err = NULL; - debug(33, 5) ("clientAccessCheckDone: '%s' answer=%d\n", http->url, answer); + debug(33, 5) ("clientAccessCheckDone: '%s' answer=%d\n", http->uri, answer); http->acl_checklist = NULL; if (answer == ACCESS_ALLOWED) { - urlCanonical(http->request, http->url); + urlCanonical(http->request, http->uri); assert(http->redirect_state == REDIRECT_NONE); http->redirect_state = REDIRECT_PENDING; redirectStart(http, clientRedirectDone, http); @@ -208,7 +207,7 @@ clientAccessCheckDone(int answer, void *data) http->entry = clientCreateStoreEntry(http, http->request->method, 0); storeAppend(http->entry, buf, strlen(buf)); } else { - debug(33, 5) ("Access Denied: %s\n", http->url); + debug(33, 5) ("Access Denied: %s\n", http->uri); http->log_type = LOG_TCP_DENIED; http->entry = clientCreateStoreEntry(http, http->request->method, 0); redirectUrl = aclGetDenyInfoUrl(&Config.denyInfoList, AclMatchedName); @@ -236,29 +235,29 @@ clientRedirectDone(void *data, char *result) size_t l; request_t *new_request = NULL; request_t *old_request = http->request; - debug(33, 5) ("clientRedirectDone: '%s' result=%s\n", http->url, + debug(33, 5) ("clientRedirectDone: '%s' result=%s\n", http->uri, result ? result : "NULL"); assert(http->redirect_state == REDIRECT_PENDING); http->redirect_state = REDIRECT_DONE; if (result) new_request = urlParse(old_request->method, result); if (new_request) { - safe_free(http->url); + safe_free(http->uri); /* need to malloc because the URL returned by the redirector might * not be big enough to append the local domain * -- David Lamkin drl@net-tel.co.uk */ l = strlen(result) + Config.appendDomainLen + 5; - http->url = xcalloc(l, 1); - xstrncpy(http->url, result, l); + http->uri = xcalloc(l, 1); + xstrncpy(http->uri, result, l); new_request->http_ver = old_request->http_ver; new_request->headers = old_request->headers; new_request->headers_sz = old_request->headers_sz; requestUnlink(old_request); http->request = requestLink(new_request); - urlCanonical(http->request, http->url); + urlCanonical(http->request, http->uri); } clientParseRequestHeaders(http); - fd_note(http->conn->fd, http->url); + fd_note(http->conn->fd, http->uri); clientProcessRequest(http); } @@ -266,13 +265,13 @@ static void clientProcessExpired(void *data) { clientHttpRequest *http = data; - char *url = http->url; + char *url = http->uri; StoreEntry *entry = NULL; - debug(33, 3) ("clientProcessExpired: '%s'\n", http->url); + debug(33, 3) ("clientProcessExpired: '%s'\n", http->uri); EBIT_SET(http->request->flags, REQ_REFRESH); http->old_entry = http->entry; entry = storeCreateEntry(url, - http->log_url, + http->log_uri, http->request->flags, http->request->method); /* NOTE, don't call storeLockObject(), storeCreateEntry() does it */ @@ -480,7 +479,7 @@ clientPurgeRequest(clientHttpRequest * http) return; } http->log_type = LOG_TCP_MISS; - k = storeKeyPublic(http->url, METHOD_GET); + k = storeKeyPublic(http->uri, METHOD_GET); if ((entry = storeGet(k)) == NULL) { http->http_code = HTTP_NOT_FOUND; } else { @@ -529,7 +528,7 @@ httpRequestFree(void *data) mem = entry->mem_obj; if (http->out.size || http->log_type) { http->al.icp.opcode = 0; - http->al.url = http->url; + http->al.url = http->uri; if (mem) { http->al.http.code = mem->reply->code; http->al.http.content_type = mem->reply->content_type; @@ -551,15 +550,16 @@ httpRequestFree(void *data) clientdbUpdate(conn->peer.sin_addr, http->log_type, PROTO_HTTP); } if (http->redirect_state == REDIRECT_PENDING) - redirectUnregister(http->url, http); + redirectUnregister(http->uri, http); if (http->acl_checklist) aclChecklistFree(http->acl_checklist); #if CHECK_FAILURE_IS_BROKE checkFailureRatio(http->log_type, http->al.hier.code); #endif - safe_free(http->url); - safe_free(http->log_url); + safe_free(http->uri); + safe_free(http->log_uri); safe_free(http->al.headers.reply); + wordlistDestroy(&http->urls); if (entry) { http->entry = NULL; storeUnregister(entry, http); @@ -648,7 +648,7 @@ clientParseRequestHeaders(clientHttpRequest * http) if (strstr(t, ThisCache)) { if (!http->accel) { debug(12, 1) ("WARNING: Forwarding loop detected for '%s'\n", - http->url); + http->uri); debug(12, 1) ("--> %s\n", t); } EBIT_SET(request->flags, REQ_LOOPDETECT); @@ -681,7 +681,7 @@ clientParseRequestHeaders(clientHttpRequest * http) static int clientCachable(clientHttpRequest * http) { - const char *url = http->url; + const char *url = http->uri; request_t *req = http->request; method_t method = req->method; const wordlist *p; @@ -712,7 +712,7 @@ clientCachable(clientHttpRequest * http) static int clientHierarchical(clientHttpRequest * http) { - const char *url = http->url; + const char *url = http->uri; request_t *request = http->request; method_t method = request->method; const wordlist *p = NULL; @@ -1145,7 +1145,7 @@ static log_type clientProcessRequest2(clientHttpRequest * http) { const request_t *r = http->request; - const cache_key *key = storeKeyPublic(http->url, r->method); + const cache_key *key = storeKeyPublic(http->uri, r->method); StoreEntry *e; if ((e = http->entry = storeGet(key)) == NULL) { /* this object isn't in the cache */ @@ -1197,7 +1197,7 @@ clientProcessRequest2(clientHttpRequest * http) static void clientProcessRequest(clientHttpRequest * http) { - char *url = http->url; + char *url = http->uri; StoreEntry *entry = NULL; request_t *r = http->request; int fd = http->conn->fd; @@ -1234,10 +1234,10 @@ clientProcessRequest(clientHttpRequest * http) http->log_type = clientProcessRequest2(http); debug(12, 4) ("clientProcessRequest: %s for '%s'\n", log_tags[http->log_type], - http->url); + http->uri); if ((entry = http->entry) != NULL) { storeLockObject(entry); - storeCreateMemObject(entry, http->url, http->log_url); + storeCreateMemObject(entry, http->uri, http->log_uri); storeClientListAdd(entry, http); } http->out.offset = 0; @@ -1278,7 +1278,7 @@ clientProcessRequest(clientHttpRequest * http) static void clientProcessMiss(clientHttpRequest * http) { - char *url = http->url; + char *url = http->uri; request_t *r = http->request; char *request_hdr = r->headers; aclCheck_t ch; @@ -1365,8 +1365,8 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status, http->conn = conn; http->start = current_time; http->req_sz = conn->in.offset; - http->url = xstrdup("error:invalid-request-method"); - http->log_url = xstrdup("error:invalid-request-method"); + http->uri = xstrdup("error:invalid-request-method"); + http->log_uri = xstrdup("error:invalid-request-method"); *headers_sz_p = conn->in.offset; *headers_p = inbuf; *method_p = METHOD_NONE; @@ -1381,8 +1381,8 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status, http->conn = conn; http->start = current_time; http->req_sz = conn->in.offset; - http->url = xstrdup("error:unsupported-request-method"); - http->log_url = xstrdup("error:unsupported-request-method"); + http->uri = xstrdup("error:unsupported-request-method"); + http->log_uri = xstrdup("error:unsupported-request-method"); *headers_sz_p = conn->in.offset; *headers_p = inbuf; *method_p = METHOD_NONE; @@ -1400,8 +1400,8 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status, http->conn = conn; http->start = current_time; http->req_sz = conn->in.offset; - http->url = xstrdup("error:missing-url"); - http->log_url = xstrdup("error:missing-url"); + http->uri = xstrdup("error:missing-url"); + http->log_uri = xstrdup("error:missing-url"); *headers_sz_p = conn->in.offset; *headers_p = inbuf; *status = -1; @@ -1418,8 +1418,8 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status, http->conn = conn; http->start = current_time; http->req_sz = conn->in.offset; - http->url = xstrdup("error:missing-http-ident"); - http->log_url = xstrdup("error:missing-http-ident"); + http->uri = xstrdup("error:missing-http-ident"); + http->log_uri = xstrdup("error:missing-http-ident"); *headers_sz_p = conn->in.offset; *headers_p = inbuf; *status = -1; @@ -1453,7 +1453,7 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status, debug(12, 5) ("parseHttpRequest: Request Header is\n%s\n", *headers_p); - /* Assign http->url */ + /* Assign http->uri */ if ((t = strchr(url, '\n'))) /* remove NL */ *t = '\0'; if ((t = strchr(url, '\r'))) /* remove CR */ @@ -1467,12 +1467,12 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status, if (vhost_mode) { /* Put the local socket IP address as the hostname */ url_sz = strlen(url) + 32 + Config.appendDomainLen; - http->url = xcalloc(url_sz, 1); - snprintf(http->url, url_sz, "http://%s:%d%s", + http->uri = xcalloc(url_sz, 1); + snprintf(http->uri, url_sz, "http://%s:%d%s", inet_ntoa(http->conn->me.sin_addr), (int) Config.Accel.port, url); - debug(12, 5) ("VHOST REWRITE: '%s'\n", http->url); + debug(12, 5) ("VHOST REWRITE: '%s'\n", http->uri); } else if (opt_accel_uses_host && (t = mime_get_header(req_hdr, "Host"))) { /* If a Host: header was specified, use it to build the URL * instead of the one in the Config file. */ @@ -1485,24 +1485,24 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status, * handling requests for non-local servers */ strtok(t, " :/;@"); url_sz = strlen(url) + 32 + Config.appendDomainLen; - http->url = xcalloc(url_sz, 1); - snprintf(http->url, url_sz, "http://%s:%d%s", + http->uri = xcalloc(url_sz, 1); + snprintf(http->uri, url_sz, "http://%s:%d%s", t, (int) Config.Accel.port, url); } else { url_sz = strlen(Config2.Accel.prefix) + strlen(url) + Config.appendDomainLen + 1; - http->url = xcalloc(url_sz, 1); - snprintf(http->url, url_sz, "%s%s", Config2.Accel.prefix, url); + http->uri = xcalloc(url_sz, 1); + snprintf(http->uri, url_sz, "%s%s", Config2.Accel.prefix, url); } http->accel = 1; } else { /* URL may be rewritten later, so make extra room */ url_sz = strlen(url) + Config.appendDomainLen + 5; - http->url = xcalloc(url_sz, 1); - strcpy(http->url, url); + http->uri = xcalloc(url_sz, 1); + strcpy(http->uri, url); http->accel = 0; } - http->log_url = xstrdup(http->url); + http->log_uri = xstrdup(http->uri); debug(12, 5) ("parseHttpRequest: Complete request received\n"); if (free_request) safe_free(url); @@ -1597,19 +1597,19 @@ clientReadRequest(int fd, void *data) errorAppendEntry(http->entry, err); break; } - if ((request = urlParse(method, http->url)) == NULL) { - debug(12, 5) ("Invalid URL: %s\n", http->url); + if ((request = urlParse(method, http->uri)) == NULL) { + debug(12, 5) ("Invalid URL: %s\n", http->uri); err = errorCon(ERR_INVALID_URL, HTTP_BAD_REQUEST); err->src_addr = conn->peer.sin_addr; - err->url = xstrdup(http->url); + err->url = xstrdup(http->uri); http->al.http.code = err->http_status; http->entry = clientCreateStoreEntry(http, method, 0); errorAppendEntry(http->entry, err); safe_free(headers); break; } - safe_free(http->log_url); - http->log_url = xstrdup(urlCanonicalClean(request)); + safe_free(http->log_uri); + http->log_uri = xstrdup(urlCanonicalClean(request)); request->client_addr = conn->peer.sin_addr; request->http_ver = http->http_ver; request->headers = headers; @@ -1624,7 +1624,10 @@ clientReadRequest(int fd, void *data) break; } http->request = requestLink(request); - clientAccessCheck(http); + if (request->protocol == PROTO_URN) + urnStart(http); + else + clientAccessCheck(http); /* * break here for NON-GET because most likely there is a * reqeust body following and we don't want to parse it diff --git a/src/enums.h b/src/enums.h index c7144e2297..63079f394d 100644 --- a/src/enums.h +++ b/src/enums.h @@ -41,6 +41,7 @@ typedef enum { ERR_ZERO_SIZE_OBJECT, ERR_FTP_DISABLED, ERR_FTP_FAILURE, + ERR_URN_RESOLVE, ERR_ACCESS_DENIED, ERR_MAX } err_type; @@ -252,6 +253,7 @@ typedef enum { PROTO_WAIS, PROTO_CACHEOBJ, PROTO_ICP, + PROTO_URN, PROTO_MAX } protocol_t; diff --git a/src/errorpage.cc b/src/errorpage.cc index ae9984c4f0..6a8ae3621a 100644 --- a/src/errorpage.cc +++ b/src/errorpage.cc @@ -1,6 +1,6 @@ /* - * $Id: errorpage.cc,v 1.110 1997/12/03 09:00:16 wessels Exp $ + * $Id: errorpage.cc,v 1.111 1997/12/06 05:16:55 wessels Exp $ * * DEBUG: section 4 Error Generation * AUTHOR: Duane Wessels @@ -236,7 +236,10 @@ errorConvert(char token, ErrorState * err) snprintf(buf, CVT_BUF_SZ, "%d", err->xerrno); break; case 'E': + if (err->xerrno) snprintf(buf, CVT_BUF_SZ, "(%d) %s", err->xerrno, strerror(err->xerrno)); + else + snprintf(buf, CVT_BUF_SZ, "(%d) -unknown-", err->xerrno); break; case 'f': /* FTP REQUEST LINE */ diff --git a/src/ftp.cc b/src/ftp.cc index 596cd8000d..75415d6df6 100644 --- a/src/ftp.cc +++ b/src/ftp.cc @@ -1,6 +1,6 @@ /* - * $Id: ftp.cc,v 1.179 1997/12/06 01:26:02 wessels Exp $ + * $Id: ftp.cc,v 1.180 1997/12/06 05:16:56 wessels Exp $ * * DEBUG: section 9 File Transfer Protocol (FTP) * AUTHOR: Harvest Derived @@ -1816,6 +1816,8 @@ ftpUrlWith2f(const request_t * request) LOCAL_ARRAY(char, portbuf, 32); char *t; portbuf[0] = '\0'; + if (request->protocol != PROTO_FTP) + return NULL; if (request->port != urlDefaultPort(request->protocol)) snprintf(portbuf, 32, ":%d", request->port); loginbuf[0] = '\0'; diff --git a/src/net_db.cc b/src/net_db.cc index fb941a27c8..e0de4251bf 100644 --- a/src/net_db.cc +++ b/src/net_db.cc @@ -1,6 +1,6 @@ /* - * $Id: net_db.cc,v 1.54 1997/12/03 01:33:15 wessels Exp $ + * $Id: net_db.cc,v 1.55 1997/12/06 05:16:57 wessels Exp $ * * DEBUG: section 37 Network Measurement Database * AUTHOR: Duane Wessels @@ -43,6 +43,7 @@ static void netdbHashDelete(const char *key); static void netdbHashLink(netdbEntry * n, const char *hostname); static void netdbHashUnlink(const char *key); static void netdbPurgeLRU(void); +static netdbEntry *netdbLookupHost(const char *key); static net_db_peer *netdbPeerByName(const netdbEntry * n, const char *); static net_db_peer *netdbPeerAdd(netdbEntry * n, peer * e); static char *netdbPeerName(const char *name); @@ -673,6 +674,7 @@ var_netdb_entry(struct variable * vp, oid * name, int *length, int exact, int *v static netdbEntry *n = NULL; static long long_return; int cnt=1; + int result; debug(49, 3) ("snmp: var_netdb_entry called with magic=%d\n", vp->magic); debug(49, 3) ("snmp: var_netdb_entry with (%d,%d)\n", *length, *var_len); diff --git a/src/protos.h b/src/protos.h index 7e3fff753a..8532a18214 100644 --- a/src/protos.h +++ b/src/protos.h @@ -77,6 +77,7 @@ extern char *clientConstructTraceEcho(clientHttpRequest *); extern void clientPurgeRequest(clientHttpRequest *); extern int checkNegativeHit(StoreEntry *); extern void clientHttpConnectionsOpen(void); +extern StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, int); extern int commSetNonBlocking(int fd); extern void commSetCloseOnExec(int fd); @@ -331,8 +332,6 @@ extern void netdbFreeMemory(void); extern int netdbHostHops(const char *host); extern int netdbHostRtt(const char *host); extern void netdbUpdatePeer(request_t *, peer * e, int rtt, int hops); -extern netdbEntry *netdbGetFirst(hash_table * table); -extern netdbEntry *netdbGetNext(hash_table * table); extern void objcachePasswdAdd(cachemgr_passwd **, char *, wordlist *); extern void objcachePasswdDestroy(cachemgr_passwd ** a); @@ -349,6 +348,9 @@ extern int protoUnregister(StoreEntry *, request_t *); extern int protoAbortFetch(StoreEntry * entry); extern DEFER protoCheckDeferRead; +extern void urnStart(clientHttpRequest *); +extern UH urnTranslateDone; + extern void redirectStart(clientHttpRequest *, RH *, void *); extern void redirectOpenServers(void); extern void redirectShutdownServers(void); diff --git a/src/redirect.cc b/src/redirect.cc index 6837a32692..f00c6c1fc0 100644 --- a/src/redirect.cc +++ b/src/redirect.cc @@ -1,6 +1,6 @@ /* - * $Id: redirect.cc,v 1.50 1997/12/02 00:17:40 wessels Exp $ + * $Id: redirect.cc,v 1.51 1997/12/06 05:16:59 wessels Exp $ * * DEBUG: section 29 Redirector * AUTHOR: Duane Wessels @@ -335,13 +335,13 @@ redirectStart(clientHttpRequest * http, RH * handler, void *data) fatal_dump("redirectStart: NULL clientHttpRequest"); if (!handler) fatal_dump("redirectStart: NULL handler"); - debug(29, 5) ("redirectStart: '%s'\n", http->url); + debug(29, 5) ("redirectStart: '%s'\n", http->uri); if (Config.Program.redirect == NULL) { handler(data, NULL); return; } r = xcalloc(1, sizeof(redirectStateData)); - r->orig_url = xstrdup(http->url); + r->orig_url = xstrdup(http->uri); r->client_addr = conn->log_addr; if (conn->ident.ident == NULL || *conn->ident.ident == '\0') { r->client_ident = dash_str; diff --git a/src/store.cc b/src/store.cc index f3b7db6772..9d2e471c5c 100644 --- a/src/store.cc +++ b/src/store.cc @@ -1,6 +1,5 @@ - /* - * $Id: store.cc,v 1.354 1997/12/02 05:06:44 wessels Exp $ + * $Id: store.cc,v 1.355 1997/12/06 05:17:01 wessels Exp $ * * DEBUG: section 20 Storeage Manager * AUTHOR: Harvest Derived diff --git a/src/structs.h b/src/structs.h index d74b3630c7..ea9c80ba32 100644 --- a/src/structs.h +++ b/src/structs.h @@ -167,6 +167,7 @@ struct _SquidConfig { time_t connect; time_t request; time_t pconn; + time_t siteSelect; } Timeout; size_t maxRequestSize; struct { @@ -508,8 +509,9 @@ struct _AccessLogEntry { struct _clientHttpRequest { ConnStateData *conn; request_t *request; /* Parsed URL ... */ - char *url; - char *log_url; + char *uri; + char *log_uri; + wordlist *urls; struct { char *buf; off_t offset; diff --git a/src/tools.cc b/src/tools.cc index 9f1890b429..c1a38f2509 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -1,6 +1,6 @@ /* - * $Id: tools.cc,v 1.133 1997/12/06 01:26:50 wessels Exp $ + * $Id: tools.cc,v 1.134 1997/12/06 05:17:03 wessels Exp $ * * DEBUG: section 21 Misc Functions * AUTHOR: Harvest Derived @@ -328,7 +328,7 @@ death(int sig) void -sigusr2_handle(int signotused) +sigusr2_handle(int sig) { static int state = 0; /* no debug() here; bad things happen if the signal is delivered during _db_print() */ @@ -460,7 +460,7 @@ debug_trap(const char *message) } void -sig_child(int signotused) +sig_child(int sig) { #ifdef _SQUID_NEXT_ union wait status; diff --git a/src/typedefs.h b/src/typedefs.h index d10089868d..c6b6a651be 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -92,7 +92,8 @@ typedef void IDCB(void *); typedef void IPH(const ipcache_addrs *, void *); typedef void IRCB(peer *, peer_t, icp_common_t *, void *data); typedef void PSC(peer *, void *); -typedef void RH(void *data, char *result); +typedef void RH(void *data, char *); +typedef void UH(void *data, wordlist *); typedef int DEFER(int fd, void *data); typedef void SIH(int fd, void *); /* swap in */ diff --git a/src/url.cc b/src/url.cc index 8c0fe01e6b..e2bb2d650c 100644 --- a/src/url.cc +++ b/src/url.cc @@ -1,6 +1,6 @@ /* - * $Id: url.cc,v 1.68 1997/11/28 08:14:09 wessels Exp $ + * $Id: url.cc,v 1.69 1997/12/06 05:17:04 wessels Exp $ * * DEBUG: section 23 URL Parsing * AUTHOR: Duane Wessels @@ -56,6 +56,7 @@ const char *ProtocolStr[] = static int url_acceptable[256]; static const char *const hex = "0123456789abcdef"; +static request_t * urnParse(method_t method, char *urn); /* convert %xx in url string to a character * Allocate a new string and return a pointer to converted string */ @@ -167,6 +168,8 @@ urlParseProtocol(const char *s) return PROTO_WAIS; if (strncasecmp(s, "cache_object", 12) == 0) return PROTO_CACHEOBJ; + if (strncasecmp(s, "urn", 3) == 0) + return PROTO_URN; return PROTO_NONE; } @@ -214,6 +217,8 @@ urlParse(method_t method, char *url) port = CONNECT_PORT; if (sscanf(url, "%[^:]:%d", host, &port) < 1) return NULL; + } else if (!strncmp(url, "urn:", 4)) { + return urnParse(method, url); } else { if (sscanf(url, "%[^:]://%[^/]%s", proto, host, urlpath) < 2) return NULL; @@ -271,6 +276,20 @@ urlParse(method_t method, char *url) return request; } +static request_t * +urnParse(method_t method, char *urn) +{ + request_t *request = NULL; + debug(50,5)("urnParse: %s\n", urn); + request = get_free_request_t(); + request->method = method; + request->protocol = PROTO_URN; + xstrncpy(request->urlpath, &urn[4], MAX_URL); + request->max_age = -1; + request->max_forwards = -1; + return request; +} + char * urlCanonical(const request_t * request, char *buf) { @@ -305,7 +324,9 @@ urlCanonicalClean(const request_t * request) LOCAL_ARRAY(char, portbuf, 32); LOCAL_ARRAY(char, loginbuf, MAX_LOGIN_SZ + 1); char *t; - switch (request->method) { + if (request->protocol == PROTO_URN) { + snprintf(buf, MAX_URL, "urn:%s", request->urlpath); + } else switch (request->method) { case METHOD_CONNECT: snprintf(buf, MAX_URL, "%s:%d", request->host, request->port); break; @@ -393,6 +414,7 @@ urlCheckRequest(const request_t * r) if (r->method == METHOD_PURGE) return 1; switch (r->protocol) { + case PROTO_URN: case PROTO_HTTP: case PROTO_CACHEOBJ: rc = 1; diff --git a/src/urn.cc b/src/urn.cc index bae6138d93..14b1c9ba70 100644 --- a/src/urn.cc +++ b/src/urn.cc @@ -1,6 +1,6 @@ /* - * DEBUG: section 50 URN Parsing + * DEBUG: section 51 URN Parsing * AUTHOR: Kostas Anagnostakis * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -29,774 +29,232 @@ #include "squid.h" -typedef struct { - void *data; - char *orig_url; - struct in_addr client_addr; - const char *client_ident; - const char *method_s; - RH *handler; -} urnStateData; +static STCB urnHandleReply; +static wordlist *urn_parsebuffer(const char *inbuf); +static const char *const crlf = "\r\n"; +static char *urnConstructMenu(clientHttpRequest * http); -struct urnQueueData { - struct urnQueueData *next; - urnStateData *urnState; -}; - -static struct urnQueueData *urnQueueHead = NULL; -static struct urnQueueData **urnQueueTailP = &urnQueueHead; - -static char **urn_parsebuffer(const char *,urnserver_t *); - -static int urnOpenServer(const char *command); -static void urnHandleRead(int, void *); -static void urnStateFree(urnStateData * ); - -static PF urnShutdownRead; -static urnserver_t **urn_child_table = NULL; -static void Enqueue (urnStateData *); -static urnStateData *Dequeue(); - - -static void -urnDispatch(urnserver_t * urn, urnStateData * r) -{ - char *buf = NULL; - clientHttpRequest *http=r->data; - - int len; - if (r->handler == NULL) { - debug(50, 1) ("urnDispatch: skipping '%s' because no handler\n", - http->urn); - urnStateFree(r); - return; - } - EBIT_SET(urn->flags, HELPER_BUSY); - urn->urnState = r; - urn->dispatch_time = current_time; - buf = get_free_8k_page(); - snprintf(buf, 8192, "%s\n", http->urn); - debug(50,1)("urnDispatch: urn=%s\n",buf); - len = strlen(buf); - comm_write(urn->outpipe, - buf, - len, - NULL, /* Handler */ - NULL, /* Handler-data */ - put_free_8k_page); - debug(50, 5) ("urnDispatch: Request sent to Redirector #%d, %d bytes\n", - urn->id, len); - commSetSelect(urn->outpipe, - COMM_SELECT_READ, - urnHandleRead, - urn, 0); - -} - -static void -urnHandleRead(int fd, void *data) -{ - urnserver_t *urnData = data; - char **x = NULL; - urnStateData *sd=urnData->urnState; - RH *handler=sd->handler; - clientHttpRequest *f = sd->data; - int len; - debug(50,5)("urnHandleRead for %s\n",f->urn); - len = read(fd, - urnData->urn_buf + urnData->offset, - urnData->size - urnData->offset); - fd_bytes(fd, len, FD_READ); - debug(50, 5) ("urnHandleRead: Result from URN ID %d (%d bytes)\n", - urnData->id, len); - if (len <= 0) { - if (len < 0 && ignoreErrno(errno)) { - commSetSelect(fd, - COMM_SELECT_READ, - urnHandleRead, - urnData, - 0); - return; - } - debug(50, EBIT_TEST(urnData->flags, HELPER_CLOSING) ? 5 : 1) - ("FD %d: Connection from URNSERVER #%d is closed, disabling\n", - fd, urnData->id); - urnData->flags = 0; - commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0); - comm_close(fd); - return; - } - urnData->offset += len; - urnData->urn_buf[urnData->offset] = '\0'; - if (strstr(urnData->urn_buf, "$end\n")) { - /* end of record found */ - x = urn_parsebuffer(urnData->urn_buf, urnData); - urnData->offset = 0; - urnData->urn_buf[0] = '\0'; - f->urls=x; - if (f->urls) - handler(f, f->urls[0]); - else - handler(f, NULL); -#ifdef HAVE_URNLOCKS - urnUnlockEntry(f); /* unlock from URN_DISPATCHED */ -#endif - } - if (urnData->offset == 0) { - urnData->data = NULL; - EBIT_CLR(urnData->flags, HELPER_BUSY); - } - /* reschedule */ - commSetSelect(urnData->inpipe, - COMM_SELECT_READ, - urnHandleRead, - urnData, 0); -} - -void -urnFindClosestStart(clientHttpRequest *http,RH *handler, void *data) +wordlist * +urnFindMinRtt(wordlist * urls, method_t m, int *rtt_ret) { - int i=0; - int avail=0; - double min_rtt=-1.0; - int min_nr=0; - static request_t *tmpr[MAX_URNTOURL]; - netdbEntry *net=NULL; - - assert(http->urls); - for (i=0;http->urls[i]!=NULL;i++) - { - tmpr[i]=urlParse(http->request->method,http->urls[i]); - debug(50,5)("Parsed %s\n",http->urls[i]); - net=netdbLookupHost(tmpr[i]->host); - if (net==NULL) - { - debug(50,5)("Pinging up %s\n",tmpr[i]->host); - netdbPingSite(tmpr[i]->host); - } - else debug(50,5)("Already here with %s and rtt=%f\n", - tmpr[i]->host,net->rtt); + int min_rtt = 0; + request_t *r; + int rtt; + wordlist *w; + wordlist *min_w = NULL; + debug(50, 1) ("urnFindMinRtt\n"); + assert(urls != NULL); + for (w = urls; w; w = w->next) { + r = urlParse(m, w->key); + if (r == NULL) + continue; + debug(50, 1) ("Parsed %s\n", w->key); + rtt = netdbHostRtt(r->host); + if (rtt == 0) { + debug(50, 1) ("Pinging %s\n", r->host); + netdbPingSite(r->host); + put_free_request_t(r); + continue; } - net=NULL; - for (i=0, avail=0;http->urls[i]!=NULL;i++) - if ((net=netdbLookupHost(tmpr[i]->host))!=NULL) - { - avail++; - if (min_rtt==-1.0 || net->rttrtt; - min_nr=i; - } - } - if (avail>1) /* we got one */ - { - http->url=http->urls[min_nr]; - urnFindClosestDone(0,http); - return; - } - - /* none received yet, must set timeout and wait */ - commSetTimeout(http->conn->fd, Config.Timeout.siteSelect, - (void *)urnFindClosestDone, http); -} - -static void -urnNudgeQueue(void) -{ - urnserver_t *urnData; - urnStateData *i = NULL; - while ((urnData = urnGetFirstAvailable()) && (i = Dequeue())) - urnDispatch(urnData, i); + debug(0, 0) ("%s rtt=%d\n", r->host, rtt); + if (rtt == 0) + continue; + if (rtt > min_rtt && min_rtt != 0) + continue; + min_rtt = rtt; + min_w = w; + put_free_request_t(r); + } + if (rtt_ret) + *rtt_ret = min_rtt; + debug(50, 1) ("Returning '%s' RTT %d\n", + min_w ? min_w->key : "NONE", + min_rtt); + return min_w; } void -urnTranslateStart(clientHttpRequest * http, RH * handler, void *data) +urnStart(clientHttpRequest * http) { - ConnStateData *conn = http->conn; - urnStateData *r = NULL; - urnserver_t *urns = NULL; - if (!http) - fatal_dump("urnTranslateStart: NULL clientHttpRequest"); - if (!handler) - fatal_dump("urnTranslateStart: NULL handler"); - debug(50, 5) ("urnStart: '%s'\n", http->urn); - if (Config.Program.urnserver == NULL) { - handler(data, NULL); - return; + LOCAL_ARRAY(char, urlres, 4096); + StoreEntry *e; + request_t *r = http->request; + request_t *urlres_r = NULL; + const cache_key *k; + char *t; + debug(50, 1) ("urnStart\n"); + assert(http != NULL); + debug(50, 1) ("urnStart: '%s'\n", http->uri); + t = strchr(r->urlpath, ':'); + if (t == NULL) { + ErrorState *err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND); + err->request = requestLink(http->request); + err->url = http->uri; + err->src_addr = http->conn->peer.sin_addr; + errorAppendEntry(http->entry, err); + return; } - r = xcalloc(1, sizeof(urnStateData)); - r->client_addr = conn->log_addr; - if (conn->ident.ident == NULL || *conn->ident.ident == '\0') { - r->client_ident = dash_str; - } else { - r->client_ident = conn->ident.ident; + *t = '\0'; + snprintf(urlres, 4096, "http://%s/uri-res/N2L?%s", r->urlpath, t+1); + k = storeKeyPublic(urlres, METHOD_GET); + urlres_r = urlParse(METHOD_GET, urlres); + urlres_r->headers = xstrdup("Accept: */*\r\n\r\n"); + urlres_r->headers_sz = strlen(urlres_r->headers); + if ((e = storeGet(k)) == NULL) { + e = storeCreateEntry(urlres, urlres, 0, METHOD_GET); + storeClientListAdd(e, http); + protoDispatch(0, e, urlres_r); } - r->method_s = RequestMethodStr[http->request->method]; - r->handler = handler; - r->data = http; - - /* - * Build a URL of the form http://host/uri-res?path - * - * Create a key - * storeGet(key); - * if NULL { - * call protoStart() or httpStart() - * } - * register to receive the data - * storeClientCopy(..., urnHandleSomething, r); - * - */ - - - if ((urns = urnGetFirstAvailable())) - { - debug(50,5)("urnTranslateStart: dispatching with %s\n",http->urn); - urnDispatch(urns, r); - } - else - Enqueue(r); -} - -static void -urnStateFree(urnStateData * r) -{ - safe_free(r->orig_url); - safe_free(r); + http->entry = e; + storeClientCopy(e, 0, 0, 4096, get_free_4k_page(), urnHandleReply, http); } static void -Enqueue(urnStateData * r) -{ - struct urnQueueData *new = xcalloc(1, sizeof(struct urnQueueData)); - new->urnState = r; - *urnQueueTailP = new; - urnQueueTailP = &new->next; -} - -static urnStateData * -Dequeue(void) -{ - struct urnQueueData *old = NULL; - urnStateData *r = NULL; - if (urnQueueHead) { - r = urnQueueHead->urnState; - old = urnQueueHead; - urnQueueHead = urnQueueHead->next; - if (urnQueueHead == NULL) - urnQueueTailP = &urnQueueHead; - safe_free(old); - } - return r; -} - - -#ifdef URN_URL_TOGETHER -request_t * -urlParse(method_t method, char *url) -{ - LOCAL_ARRAY(char, proto, MAX_URL); - LOCAL_ARRAY(char, login, MAX_URL); - LOCAL_ARRAY(char, host, MAX_URL); - LOCAL_ARRAY(char, urlpath, MAX_URL); - request_t *request = NULL; - char *t = NULL; - int port; - protocol_t protocol = PROTO_NONE; - int l; - proto[0] = host[0] = urlpath[0] = login[0] = '\0'; - - if ((l = strlen(url)) + Config.appendDomainLen > (MAX_URL - 1)) { - /* terminate so it doesn't overflow other buffers */ - *(url + (MAX_URL >> 1)) = '\0'; - debug(50, 0) ("urlParse: URL too large (%d bytes)\n", l); - return NULL; - } - if (method == METHOD_CONNECT) { - port = CONNECT_PORT; - if (sscanf(url, "%[^:]:%d", host, &port) < 1) - return NULL; - } else { - if (sscanf(url, "%[^:]://%[^/]%s", proto, host, urlpath) < 2) - return NULL; - protocol = urlParseProtocol(proto); - port = urlDefaultPort(protocol); - /* Is there any login informaiton? */ - if ((t = strrchr(host, '@'))) { - strcpy(login, host); - t = strrchr(login, '@'); - *t = 0; - strcpy(host, t + 1); - } - if ((t = strrchr(host, ':'))) { - *t++ = '\0'; - if (*t != '\0') - port = atoi(t); - } - } - for (t = host; *t; t++) - *t = tolower(*t); - /* remove trailing dots from hostnames */ - while ((l = strlen(host)) > 0 && host[--l] == '.') - host[l] = '\0'; - if (Config.appendDomain && !strchr(host, '.')) - strncat(host, Config.appendDomain, SQUIDHOSTNAMELEN); - if (port == 0) { - debug(50, 0) ("urlParse: Invalid port == 0\n"); - return NULL; - } -#ifdef HARDCODE_DENY_PORTS - /* These ports are filtered in the default squid.conf, but - * maybe someone wants them hardcoded... */ - if (port == 7 || port == 9 || port = 19) { - debug(50, 0) ("urlParse: Deny access to port %d\n", port); - return NULL; - } -#endif -#ifdef REMOVE_FTP_TRAILING_SLASHES - /* remove trailing slashes from FTP URLs */ - if (protocol == PROTO_FTP) { - t = urlpath + strlen(urlpath); - while (t > urlpath && *(--t) == '/') - *t = '\0'; - } -#endif - request = get_free_request_t(); - request->method = method; - request->protocol = protocol; - xstrncpy(request->host, host, SQUIDHOSTNAMELEN); - xstrncpy(request->login, login, MAX_LOGIN_SZ); - request->port = (u_short) port; - xstrncpy(request->urlpath, urlpath, MAX_URL); - request->max_age = -1; - request->max_forwards = -1; - return request; -} - -char * -urlCanonical(const request_t * request, char *buf) +urnHandleReply(void *data, char *buf, ssize_t size) { - LOCAL_ARRAY(char, urlbuf, MAX_URL); - LOCAL_ARRAY(char, portbuf, 32); - if (buf == NULL) - buf = urlbuf; - switch (request->method) { - case METHOD_CONNECT: - snprintf(buf, MAX_URL, "%s:%d", request->host, request->port); - break; - default: - portbuf[0] = '\0'; - if (request->port != urlDefaultPort(request->protocol)) - snprintf(portbuf, 32, ":%d", request->port); - snprintf(buf, MAX_URL, "%s://%s%s%s%s%s", - ProtocolStr[request->protocol], - request->login, - *request->login ? "@" : null_string, - request->host, - portbuf, - request->urlpath); - break; + clientHttpRequest *http = data; + StoreEntry *entry = http->entry; + char *s = NULL; + wordlist *urls = NULL; + debug(50, 1) ("urnHandleReply: Called with size=%d.\n", size); + if (entry->store_status == STORE_ABORTED) { + put_free_4k_page(buf); + return; } - return buf; -} - -char * -urlCanonicalClean(const request_t * request) -{ - LOCAL_ARRAY(char, buf, MAX_URL); - LOCAL_ARRAY(char, portbuf, 32); - LOCAL_ARRAY(char, loginbuf, MAX_LOGIN_SZ + 1); - char *t; - switch (request->method) { - case METHOD_CONNECT: - snprintf(buf, MAX_URL, "%s:%d", request->host, request->port); - break; - default: - portbuf[0] = '\0'; - if (request->port != urlDefaultPort(request->protocol)) - snprintf(portbuf, 32, ":%d", request->port); - loginbuf[0] = '\0'; - if (strlen(request->login) > 0) { - strcpy(loginbuf, request->login); - if ((t = strchr(loginbuf, ':'))) - *t = '\0'; - strcat(loginbuf, "@"); - } - snprintf(buf, MAX_URL, "%s://%s%s%s%s", - ProtocolStr[request->protocol], - loginbuf, - request->host, - portbuf, - request->urlpath); - if ((t = strchr(buf, '?'))) - *t = '\0'; - break; + if (size == 0) { + put_free_4k_page(buf); + return; + } else if (size < 0) { + put_free_4k_page(buf); + return; } - return buf; -} - -char * -urlClean(char *dirty) -{ - char *clean; - request_t *r = urlParse(METHOD_GET, dirty); - if (r == NULL) - return dirty; - clean = urlCanonicalClean(r); - put_free_request_t(r); - return clean; -} - - -request_t * -requestLink(request_t * request) -{ - request->link_count++; - return request; -} - -void -requestUnlink(request_t * request) -{ - if (request == NULL) + if (entry->store_status == STORE_PENDING) { + storeClientCopy(entry, + entry->mem_obj->inmem_hi, + 0, + SM_PAGE_SIZE, + buf, + urnHandleReply, + http); return; - request->link_count--; - if (request->link_count) + } + /* we know its STORE_OK */ + s = mime_headers_end(buf); + if (s == NULL) { + debug(0, 0) ("urnHandleReply: didn't find end-of-headers for %s\n", + storeUrl(entry)); return; - safe_free(request->headers); - put_free_request_t(request); -} - -int -matchDomainName(const char *domain, const char *host) -{ - int offset; - if ((offset = strlen(host) - strlen(domain)) < 0) - return 0; /* host too short */ - if (strcasecmp(domain, host + offset) != 0) - return 0; /* no match at all */ - if (*domain == '.') - return 1; - if (*(host + offset - 1) == '.') - return 1; - if (offset == 0) - return 1; - return 0; -} - -int -urlCheckRequest(const request_t * r) -{ - int rc = 0; - if (r->method == METHOD_CONNECT) - return 1; - if (r->method == METHOD_TRACE) - return 1; - if (r->method == METHOD_PURGE) - return 1; - switch (r->protocol) { - case PROTO_HTTP: - case PROTO_CACHEOBJ: - rc = 1; - break; - case PROTO_FTP: - if (r->method == METHOD_PUT) - rc = 1; - case PROTO_GOPHER: - case PROTO_WAIS: - if (r->method == METHOD_GET) - rc = 1; - else if (r->method == METHOD_HEAD) - rc = 1; - break; - default: - break; } - return rc; -} -#endif - - - -void -urnShutdownServers(void) -{ - urnserver_t *urn = NULL; - int k; - - debug(50, 3) ("urnShutdownServers:\n"); - - for (k = 0; k < NUrnServersAlloc; k++) { - urn = *(urn_child_table + k); - if (!EBIT_TEST(urn->flags, HELPER_ALIVE)) { - debug(50, 3) ("urnShutdownServers: #%d is NOT ALIVE.\n", urn->id); - continue; - } - if (EBIT_TEST(urn->flags, HELPER_BUSY)) { - debug(50, 3) ("urnShutdownServers: #%d is BUSY.\n", urn->id); - EBIT_SET(urn->flags, HELPER_SHUTDOWN); - continue; - } - if (EBIT_TEST(urn->flags, HELPER_CLOSING)) { - debug(50, 3) ("urnShutdownServers: #%d is CLOSING.\n", urn->id); - continue; - } - urnShutdownServer(urn); + assert(http->entry->mem_obj); + assert(http->entry->mem_obj->reply); + httpParseReplyHeaders(buf, http->entry->mem_obj->reply); + debug(50, 1) ("mem->reply exists, code=%d.\n", + http->entry->mem_obj->reply->code); + if (http->entry->mem_obj->reply->code != 200) { + debug(50, 1) ("urnHandleReply: failed.\n"); + /* XX - return error message */ + urnTranslateDone(http, NULL); + return; } + while (isspace(*s)) + s++; + urls = urn_parsebuffer(s); + urnTranslateDone(http, urls); + put_free_4k_page(buf); } -void -urnShutdownServer(urnserver_t * urn) -{ - static char *shutdown_cmd = "$shutdown\n"; - debug(50, 3) ("urnShutdownServer: sending '$shutdown' to urnserver #%d\n", - urn->id); - debug(50, 3) ("urnShutdownServer: --> FD %d\n", urn->outpipe); - cbdataLock(urn); - comm_write(urn->outpipe, - xstrdup(shutdown_cmd), - strlen(shutdown_cmd), - NULL, /* Handler */ - NULL, /* Handler-data */ - xfree); - commSetSelect(urn->inpipe, - COMM_SELECT_READ, - urnShutdownRead, - urn, - 0); - EBIT_SET(urn->flags, HELPER_CLOSING); -} - -static void -urnShutdownRead(int fd, void *data) -{ - urnserver_t *urn = data; - debug(50, EBIT_TEST(urn->flags, HELPER_CLOSING) ? 5 : 1) - ("FD %d: Connection from URNSERVER #%d is closed, disabling\n", - fd, - urn->id); - urn->flags = 0; - commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0); - cbdataUnlock(urn); - comm_close(fd); -} -void -urnOpenServers(void) +static wordlist * +urn_parsebuffer(const char *inbuf) { - int N = Config.urnChildren; - char *prg = Config.Program.urnserver; - int k; - int urnsocket; - LOCAL_ARRAY(char, fd_note_buf, FD_DESC_SZ); - char *s; - - urnFreeMemory(); - urn_child_table = xcalloc(N, sizeof(urnserver_t *)); - NUrnServersAlloc = 0; - for (k = 0; k < N; k++) { - urn_child_table[k] = xcalloc(1, sizeof(urnserver_t)); - cbdataAdd(urn_child_table[k]); - if ((urnsocket = urnOpenServer(prg)) < 0) { - debug(50, 1) ("urnOpenServers: WARNING: Failed to start 'urnserver' #%d. %s \n", k + 1, prg); - EBIT_CLR(urn_child_table[k]->flags, HELPER_ALIVE); - urn_child_table[k]->id = k + 1; - urn_child_table[k]->inpipe = -1; - urn_child_table[k]->outpipe = -1; - } else { - debug(50, 4) ("urnOpenServers: FD %d connected to %s #%d.\n", - urnsocket, prg, k + 1); - EBIT_SET(urn_child_table[k]->flags, HELPER_ALIVE); - urn_child_table[k]->id = k + 1; - urn_child_table[k]->inpipe = urnsocket; - urn_child_table[k]->outpipe = urnsocket; - urn_child_table[k]->answer = squid_curtime; - urn_child_table[k]->dispatch_time = current_time; - urn_child_table[k]->size = URN_INBUF_SZ - 1; - urn_child_table[k]->offset = 0; - if ((s = strrchr(prg, '/'))) - s++; - else - s = prg; - snprintf(fd_note_buf, FD_DESC_SZ, "%s #%d", s, urn_child_table[k]->id); - fd_note(urn_child_table[k]->inpipe, fd_note_buf); - commSetNonBlocking(urn_child_table[k]->inpipe); - debug(50, 3) ("urnOpenServers: 'urn_server' %d started\n", k); - NUrnServersAlloc++; - } + char *buf = xstrdup(inbuf); + char *token; + wordlist *u; + wordlist *head = NULL; + wordlist **last = &head; + debug(50, 1) ("urn_parsebuffer\n"); + for (token = strtok(buf, crlf); token; token = strtok(NULL, crlf)) { + debug(0, 0) ("urn_parsebuffer: got '%s'\n", token); + u = xmalloc(sizeof(wordlist)); + u->key = xstrdup(token); + u->next = NULL; + *last = u; + last = &u->next; } - if (NUrnServersAlloc == 0 && Config.urnChildren > 0) - fatal("Failed to start any urnservers"); - debug(50, 1) ("Started %d 'urnserver' processes\n", NUrnServersAlloc); + return head; } void -urnFreeMemory(void) -{ - int k; - /* free old structures if present */ - if (urn_child_table) { - for (k = 0; k < NUrnServersAlloc; k++) - cbdataFree(urn_child_table[k]); - safe_free(urn_child_table); - } -} -urnserver_t * -urnGetFirstAvailable(void) -{ - int k; - urnserver_t *urn = NULL; - for (k = 0; k < NUrnServersAlloc; k++) { - urn = *(urn_child_table + k); - if (EBIT_TEST(urn->flags, HELPER_BUSY)) - continue; - if (EBIT_TEST(urn->flags, HELPER_CLOSING)) - continue; - if (!EBIT_TEST(urn->flags, HELPER_ALIVE)) - continue; - return urn; - } - return NULL; -} - -static int -urnOpenServer(const char *command) +urnTranslateDone(void *data, wordlist * urls) { - pid_t pid; - struct sockaddr_in S; - int cfd; - int sfd; - int fd; - int len; - LOCAL_ARRAY(char, buf, 128); - - cfd = comm_open(SOCK_STREAM, - 0, - local_addr, - 0, - COMM_NOCLOEXEC, - "urnserver listen socket"); - if (cfd < 0) { - debug(50, 0) ("urnOpenServer: Failed to create urnserver\n"); - return -1; - } - len = sizeof(S); - memset(&S, '\0', len); - if (getsockname(cfd, (struct sockaddr *) &S, &len) < 0) { - debug(50, 5) ("urnOpenServer: getsockname: %s\n", xstrerror()); - comm_close(cfd); - return -1; - } - listen(cfd, 1); - - /* flush or else we get dup data if unbuffered_logs is set */ - logsFlush(); - if ((pid = fork()) < 0) { - debug(50, 5) ("urnOpenServer: fork: %s\n", xstrerror()); - comm_close(cfd); - fprintf(stderr,"ERR 1\n"); - return -1; - } - if (pid > 0) { /* parent */ - comm_close(cfd); /* close shared socket with child */ - /* open new socket for parent process */ - sfd = comm_open(SOCK_STREAM, - 0, /* protocol */ - local_addr, - 0, /* port */ - 0, /* flags */ - "squid <-> urnserver"); - if (sfd == COMM_ERROR) { - comm_close(sfd); - return -1; - } - if (comm_connect_addr(sfd, &S) == COMM_ERROR) { - comm_close(sfd); - return -1; - } - if (write(sfd, "$hello\n", 7) < 0) { - debug(50, 0) ("urnOpenServer: $hello write test failed \n"); - perror("squid"); - comm_close(sfd); - return -1; - } - memset(buf, '\0', 128); - if (read(sfd, buf, 127) < 0) { - debug(50, 0) ("urnOpenServer: $hello read test failed\n"); - debug(50, 0) ("--> read: %s\n", xstrerror()); - comm_close(sfd); - return -1; - } else if (strcmp(buf, "$alive\n$end\n")) { - debug(50, 0) ("urnOpenServer: $hello read test failed\n"); - debug(50, 0) ("--> got '%s'\n", rfc1738_escape(buf)); - comm_close(sfd); - return -1; - } - commSetTimeout(sfd, -1, NULL, NULL); - return sfd; + clientHttpRequest *http = data; + request_t *new_request = NULL; + request_t *old_request = http->request; + ErrorState *err = NULL; + wordlist *min_w; + char *buf; + debug(50, 1) ("urnTranslateDone\n"); + if ((http->urls = urls) == NULL) { /* unkown URN error */ + debug(50, 1) ("urnTranslateDone: unknown URN (%s).\n", http->uri); + http->entry = clientCreateStoreEntry(http, old_request->method, 0); + err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND); + err->request = requestLink(http->request); + err->url = http->uri; + err->src_addr = http->conn->peer.sin_addr; + errorAppendEntry(http->entry, err); + return; } - /* child */ - if ((fd = accept(cfd, NULL, NULL)) < 0) { - debug(50, 0) ("urnOpenServer: FD %d accept: %s\n", cfd, xstrerror()); - exit(1); + min_w = urnFindMinRtt(http->urls, http->request->method, NULL); + if (min_w != NULL) { + safe_free(http->uri); + http->uri = xstrdup(min_w->key); + new_request = urlParse(old_request->method, http->uri); + new_request->http_ver = old_request->http_ver; + new_request->headers = old_request->headers; + new_request->headers_sz = old_request->headers_sz; + requestUnlink(http->request); + http->request = requestLink(new_request); + clientAccessCheck(http); + } else { + buf = urnConstructMenu(http); + storeAppend(http->entry, buf, strlen(buf)); + storeComplete(http->entry); } - dup2(fd, 0); - dup2(fd, 1); - dup2(fileno(debug_log), 2); - fclose(debug_log); - close(fd); - close(cfd); - - execlp(command, "(urnserver)", NULL); - debug(50, 0) ("urnOpenServer: %s: %s\n", command, xstrerror()); - _exit(1); - return 0; } -static char ** -urn_parsebuffer(const char *inbuf, urnserver_t * urnData) +static char * +urnConstructMenu(clientHttpRequest * http) { - char *buf = xstrdup(inbuf); - char *token; - char **urls=NULL; - int k; - int urlcount; - - debug(50, 5) ("urn_parsebuffer: parsing:\n%s", inbuf); - for (token = strtok(buf, w_space); token; token = strtok(NULL, w_space)) { - if (!strcmp(token, "$end")) { - break; - } else if (!strcmp(token, "$none")) { - return NULL; - } else if (!strcmp(token, "$alive")) { - urnData->answer = squid_curtime; - } else if (!strcmp(token, "$fail")) { - if ((token = strtok(NULL, "\n")) == NULL) - fatal_dump("Invalid $fail"); - } else if (!strcmp(token, "$message")) { - if ((token = strtok(NULL, "\n")) == NULL) - fatal_dump("Invalid $message"); - } else if (!strcmp(token, "$urlcount")) { - if ((token = strtok(NULL, w_space)) == NULL) - fatal_dump("Invalid $urlcount"); - urlcount = atoi(token); - if (urlcount== 0 ) - return NULL; - if (urls==NULL) - urls=xmalloc((urlcount+1)*sizeof(char *)); - for (k = 0; k < urlcount; k++) { - if ((token = strtok(NULL, w_space)) == NULL) - fatal_dump("Invalid URL"); - urls[k]=xstrdup(token); - } - urls[k]=NULL; - } else { - debug(50, 0) ("--> %s <--\n", inbuf); - debug_trap("Invalid urnserver output"); - } + LOCAL_ARRAY(char, buf, 8192); + LOCAL_ARRAY(char, line, 256); + LOCAL_ARRAY(char, content, 4096); + char *hdr; + wordlist *w; + debug(50, 1) ("urnConstructMenu\n"); + memset(buf, '\0', 8192); + memset(content, '\0', 4096); + assert(http->urls); + for (w = http->urls; w; w = w->next) { + snprintf(line, 256, "
  • %s\n", w->key, w->key); + strcat(buf, line); } - xfree(buf); - - return (urls); + snprintf(content, 4096, + "Select URL for %s\n" + "

    Select URL for %s

    \n" + "
    \n" + "
    \n" + "Generated by %s/%s@%s\n" + "
    \n", + http->uri, http->uri, buf, appname, version_string, getMyHostname()); + memset(buf, '\0', 8192); + hdr = httpReplyHeader(1.0, + HTTP_OK, + "text/html", + strlen(content), + 0, + squid_curtime); + snprintf(buf, 8192, "%s\r\n%s", + hdr, + content); + return buf; } - -- 2.47.2