--------------------- PatchSet 5266 Date: 2002/10/07 02:04:10 Author: rbcollins Branch: rbcollins_cxxtest Tag: (none) Log: more files Members: src/Makefile.am:1.29.2.9->1.29.2.10 src/ident.c:1.10->1.10.6.1(DEAD) src/ident.cc:1.1->1.1.2.1 src/send-announce.c:1.8->1.8.20.1(DEAD) src/send-announce.cc:1.1->1.1.2.1 src/unlinkd.c:1.9->1.9.14.1(DEAD) src/unlinkd.cc:1.1->1.1.2.1 src/urn.c:1.18.2.1->1.18.2.2(DEAD) src/urn.cc:1.1->1.1.2.1 Index: squid/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Makefile.am,v retrieving revision 1.29.2.9 retrieving revision 1.29.2.10 diff -u -r1.29.2.9 -r1.29.2.10 --- squid/src/Makefile.am 6 Oct 2002 12:31:52 -0000 1.29.2.9 +++ squid/src/Makefile.am 7 Oct 2002 02:04:10 -0000 1.29.2.10 @@ -169,7 +169,7 @@ icmp.c \ icp_v2.c \ icp_v3.c \ - ident.c \ + ident.cc \ internal.c \ ipc.c \ ipcache.c \ @@ -193,7 +193,7 @@ redirect.cc \ referer.c \ refresh.c \ - send-announce.c \ + send-announce.cc \ $(SNMPSOURCE) \ squid.h \ ssl.c \ --- squid/src/ident.c Wed Feb 14 01:07:34 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,244 +0,0 @@ - -/* - * $Id: ident.c,v 1.10 2002/09/15 11:06:32 rbcollins Exp $ - * - * DEBUG: section 30 Ident (RFC 931) - * AUTHOR: Duane Wessels - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; 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" - -#if USE_IDENT - -#define IDENT_PORT 113 -#define IDENT_KEY_SZ 50 - -typedef struct _IdentClient { - IDCB *callback; - void *callback_data; - struct _IdentClient *next; -} IdentClient; - -typedef struct _IdentStateData { - hash_link hash; /* must be first */ - int fd; /* IDENT fd */ - struct sockaddr_in me; - struct sockaddr_in my_peer; - IdentClient *clients; -} IdentStateData; - -static PF identReadReply; -static PF identClose; -static PF identTimeout; -static CNCB identConnectDone; -static hash_table *ident_hash = NULL; -static void identClientAdd(IdentStateData *, IDCB *, void *); - -/**** PRIVATE FUNCTIONS ****/ - -static void -identCallback(IdentStateData * state, char *result) -{ - IdentClient *client; - if (result && *result == '\0') - result = NULL; - while ((client = state->clients)) { - void *cbdata; - state->clients = client->next; - if (cbdataReferenceValidDone(client->callback_data, &cbdata)) - client->callback(result, cbdata); - xfree(client); - } -} - -static void -identClose(int fdnotused, void *data) -{ - IdentStateData *state = data; - identCallback(state, NULL); - comm_close(state->fd); - hash_remove_link(ident_hash, (hash_link *) state); - cbdataFree(state); -} - -static void -identTimeout(int fd, void *data) -{ - IdentStateData *state = data; - debug(30, 3) ("identTimeout: FD %d, %s\n", fd, - inet_ntoa(state->my_peer.sin_addr)); - comm_close(fd); -} - -static void -identConnectDone(int fd, comm_err_t status, void *data) -{ - IdentStateData *state = data; - IdentClient *c; - MemBuf mb; - if (status != COMM_OK) { - /* Failed to connect */ - comm_close(fd); - return; - } - /* - * see if any of our clients still care - */ - for (c = state->clients; c; c = c->next) { - if (cbdataReferenceValid(c->callback_data)) - break; - } - if (c == NULL) { - /* no clients care */ - comm_close(fd); - return; - } - memBufDefInit(&mb); - memBufPrintf(&mb, "%d, %d\r\n", - ntohs(state->my_peer.sin_port), - ntohs(state->me.sin_port)); - comm_write_mbuf(fd, mb, NULL, state); - commSetSelect(fd, COMM_SELECT_READ, identReadReply, state, 0); - commSetTimeout(fd, Config.Timeout.ident, identTimeout, state); -} - -static void -identReadReply(int fd, void *data) -{ - IdentStateData *state = data; - LOCAL_ARRAY(char, buf, BUFSIZ); - char *ident = NULL; - char *t = NULL; - int len = -1; - buf[0] = '\0'; - statCounter.syscalls.sock.reads++; - len = FD_READ_METHOD(fd, buf, BUFSIZ - 1); - fd_bytes(fd, len, FD_READ); - if (len <= 0) { - comm_close(fd); - return; - } - /* - * XXX This isn't really very tolerant. It should read until EOL - * or EOF and then decode the answer... If the reply is fragmented - * then this will fail - */ - buf[len] = '\0'; - if ((t = strchr(buf, '\r'))) - *t = '\0'; - if ((t = strchr(buf, '\n'))) - *t = '\0'; - debug(30, 5) ("identReadReply: FD %d: Read '%s'\n", fd, buf); - if (strstr(buf, "USERID")) { - if ((ident = strrchr(buf, ':'))) { - while (xisspace(*++ident)); - identCallback(state, ident); - } - } - comm_close(fd); -} - - -static void -identClientAdd(IdentStateData * state, IDCB * callback, void *callback_data) -{ - IdentClient *c = xcalloc(1, sizeof(*c)); - IdentClient **C; - c->callback = callback; - c->callback_data = cbdataReference(callback_data); - for (C = &state->clients; *C; C = &(*C)->next); - *C = c; -} - -CBDATA_TYPE(IdentStateData); - -/**** PUBLIC FUNCTIONS ****/ - -/* - * start a TCP connection to the peer host on port 113 - */ -void -identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, void *data) -{ - IdentStateData *state; - int fd; - char key1[IDENT_KEY_SZ]; - char key2[IDENT_KEY_SZ]; - char key[IDENT_KEY_SZ]; - snprintf(key1, IDENT_KEY_SZ, "%s:%d", - inet_ntoa(me->sin_addr), - ntohs(me->sin_port)); - snprintf(key2, IDENT_KEY_SZ, "%s:%d", - inet_ntoa(my_peer->sin_addr), - ntohs(my_peer->sin_port)); - snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2); - if ((state = hash_lookup(ident_hash, key)) != NULL) { - identClientAdd(state, callback, data); - return; - } - fd = comm_open(SOCK_STREAM, - 0, - me->sin_addr, - 0, - COMM_NONBLOCKING, - "ident"); - if (fd == COMM_ERROR) { - /* Failed to get a local socket */ - callback(NULL, data); - return; - } - CBDATA_INIT_TYPE(IdentStateData); - state = cbdataAlloc(IdentStateData); - state->hash.key = xstrdup(key); - state->fd = fd; - state->me = *me; - state->my_peer = *my_peer; - identClientAdd(state, callback, data); - hash_join(ident_hash, &state->hash); - comm_add_close_handler(fd, - identClose, - state); - commSetTimeout(fd, Config.Timeout.ident, identTimeout, state); - commConnectStart(fd, - inet_ntoa(state->my_peer.sin_addr), - IDENT_PORT, - identConnectDone, - state); -} - -void -identInit(void) -{ - ident_hash = hash_create((HASHCMP *) strcmp, - hashPrime(Squid_MaxFD / 8), - hash4); -} - -#endif --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/ident.cc Wed Feb 14 01:07:34 2007 @@ -0,0 +1,244 @@ + +/* + * $Id: ident.cc,v 1.1.2.1 2002/10/07 02:04:10 rbcollins Exp $ + * + * DEBUG: section 30 Ident (RFC 931) + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; 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" + +#if USE_IDENT + +#define IDENT_PORT 113 +#define IDENT_KEY_SZ 50 + +typedef struct _IdentClient { + IDCB *callback; + void *callback_data; + struct _IdentClient *next; +} IdentClient; + +typedef struct _IdentStateData { + hash_link hash; /* must be first */ + int fd; /* IDENT fd */ + struct sockaddr_in me; + struct sockaddr_in my_peer; + IdentClient *clients; +} IdentStateData; + +static PF identReadReply; +static PF identClose; +static PF identTimeout; +static CNCB identConnectDone; +static hash_table *ident_hash = NULL; +static void identClientAdd(IdentStateData *, IDCB *, void *); + +/**** PRIVATE FUNCTIONS ****/ + +static void +identCallback(IdentStateData * state, char *result) +{ + IdentClient *client; + if (result && *result == '\0') + result = NULL; + while ((client = state->clients)) { + void *cbdata; + state->clients = client->next; + if (cbdataReferenceValidDone(client->callback_data, &cbdata)) + client->callback(result, cbdata); + xfree(client); + } +} + +static void +identClose(int fdnotused, void *data) +{ + IdentStateData *state = data; + identCallback(state, NULL); + comm_close(state->fd); + hash_remove_link(ident_hash, (hash_link *) state); + cbdataFree(state); +} + +static void +identTimeout(int fd, void *data) +{ + IdentStateData *state = data; + debug(30, 3) ("identTimeout: FD %d, %s\n", fd, + inet_ntoa(state->my_peer.sin_addr)); + comm_close(fd); +} + +static void +identConnectDone(int fd, comm_err_t status, void *data) +{ + IdentStateData *state = data; + IdentClient *c; + MemBuf mb; + if (status != COMM_OK) { + /* Failed to connect */ + comm_close(fd); + return; + } + /* + * see if any of our clients still care + */ + for (c = state->clients; c; c = c->next) { + if (cbdataReferenceValid(c->callback_data)) + break; + } + if (c == NULL) { + /* no clients care */ + comm_close(fd); + return; + } + memBufDefInit(&mb); + memBufPrintf(&mb, "%d, %d\r\n", + ntohs(state->my_peer.sin_port), + ntohs(state->me.sin_port)); + comm_write_mbuf(fd, mb, NULL, state); + commSetSelect(fd, COMM_SELECT_READ, identReadReply, state, 0); + commSetTimeout(fd, Config.Timeout.ident, identTimeout, state); +} + +static void +identReadReply(int fd, void *data) +{ + IdentStateData *state = data; + LOCAL_ARRAY(char, buf, BUFSIZ); + char *ident = NULL; + char *t = NULL; + int len = -1; + buf[0] = '\0'; + statCounter.syscalls.sock.reads++; + len = FD_READ_METHOD(fd, buf, BUFSIZ - 1); + fd_bytes(fd, len, FD_READ); + if (len <= 0) { + comm_close(fd); + return; + } + /* + * XXX This isn't really very tolerant. It should read until EOL + * or EOF and then decode the answer... If the reply is fragmented + * then this will fail + */ + buf[len] = '\0'; + if ((t = strchr(buf, '\r'))) + *t = '\0'; + if ((t = strchr(buf, '\n'))) + *t = '\0'; + debug(30, 5) ("identReadReply: FD %d: Read '%s'\n", fd, buf); + if (strstr(buf, "USERID")) { + if ((ident = strrchr(buf, ':'))) { + while (xisspace(*++ident)); + identCallback(state, ident); + } + } + comm_close(fd); +} + + +static void +identClientAdd(IdentStateData * state, IDCB * callback, void *callback_data) +{ + IdentClient *c = xcalloc(1, sizeof(*c)); + IdentClient **C; + c->callback = callback; + c->callback_data = cbdataReference(callback_data); + for (C = &state->clients; *C; C = &(*C)->next); + *C = c; +} + +CBDATA_TYPE(IdentStateData); + +/**** PUBLIC FUNCTIONS ****/ + +/* + * start a TCP connection to the peer host on port 113 + */ +void +identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, void *data) +{ + IdentStateData *state; + int fd; + char key1[IDENT_KEY_SZ]; + char key2[IDENT_KEY_SZ]; + char key[IDENT_KEY_SZ]; + snprintf(key1, IDENT_KEY_SZ, "%s:%d", + inet_ntoa(me->sin_addr), + ntohs(me->sin_port)); + snprintf(key2, IDENT_KEY_SZ, "%s:%d", + inet_ntoa(my_peer->sin_addr), + ntohs(my_peer->sin_port)); + snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2); + if ((state = hash_lookup(ident_hash, key)) != NULL) { + identClientAdd(state, callback, data); + return; + } + fd = comm_open(SOCK_STREAM, + 0, + me->sin_addr, + 0, + COMM_NONBLOCKING, + "ident"); + if (fd == COMM_ERROR) { + /* Failed to get a local socket */ + callback(NULL, data); + return; + } + CBDATA_INIT_TYPE(IdentStateData); + state = cbdataAlloc(IdentStateData); + state->hash.key = xstrdup(key); + state->fd = fd; + state->me = *me; + state->my_peer = *my_peer; + identClientAdd(state, callback, data); + hash_join(ident_hash, &state->hash); + comm_add_close_handler(fd, + identClose, + state); + commSetTimeout(fd, Config.Timeout.ident, identTimeout, state); + commConnectStart(fd, + inet_ntoa(state->my_peer.sin_addr), + IDENT_PORT, + identConnectDone, + state); +} + +void +identInit(void) +{ + ident_hash = hash_create((HASHCMP *) strcmp, + hashPrime(Squid_MaxFD / 8), + hash4); +} + +#endif --- squid/src/send-announce.c Wed Feb 14 01:07:34 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,109 +0,0 @@ - -/* - * $Id: send-announce.c,v 1.8 2002/04/04 23:14:08 squidadm Exp $ - * - * DEBUG: section 27 Cache Announcer - * AUTHOR: Duane Wessels - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; 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 IPH send_announce; - -void -start_announce(void *datanotused) -{ - if (0 == Config.onoff.announce) - return; - if (theOutIcpConnection < 0) - return; - ipcache_nbgethostbyname(Config.Announce.host, send_announce, NULL); - eventAdd("send_announce", start_announce, NULL, (double) Config.Announce.period, 1); -} - -static void -send_announce(const ipcache_addrs * ia, void *junk) -{ - LOCAL_ARRAY(char, tbuf, 256); - LOCAL_ARRAY(char, sndbuf, BUFSIZ); - struct sockaddr_in S; - char *host = Config.Announce.host; - char *file = NULL; - u_short port = Config.Announce.port; - int l; - int n; - int fd; - int x; - if (ia == NULL) { - debug(27, 1) ("send_announce: Unknown host '%s'\n", host); - return; - } - debug(27, 1) ("Sending Announcement to %s\n", host); - sndbuf[0] = '\0'; - snprintf(tbuf, 256, "cache_version SQUID/%s\n", version_string); - strcat(sndbuf, tbuf); - assert(Config.Sockaddr.http); - snprintf(tbuf, 256, "Running on %s %d %d\n", - getMyHostname(), - getMyPort(), - (int) Config.Port.icp); - strcat(sndbuf, tbuf); - if (Config.adminEmail) { - snprintf(tbuf, 256, "cache_admin: %s\n", Config.adminEmail); - strcat(sndbuf, tbuf); - } - snprintf(tbuf, 256, "generated %d [%s]\n", - (int) squid_curtime, - mkhttpdlogtime(&squid_curtime)); - strcat(sndbuf, tbuf); - l = strlen(sndbuf); - if ((file = Config.Announce.file) != NULL) { - fd = file_open(file, O_RDONLY | O_TEXT); - if (fd > -1 && (n = FD_READ_METHOD(fd, sndbuf + l, BUFSIZ - l - 1)) > 0) { - fd_bytes(fd, n, FD_READ); - l += n; - sndbuf[l] = '\0'; - file_close(fd); - } else { - debug(50, 1) ("send_announce: %s: %s\n", file, xstrerror()); - } - } - memset(&S, '\0', sizeof(S)); - S.sin_family = AF_INET; - S.sin_port = htons(port); - S.sin_addr = ia->in_addrs[0]; - assert(theOutIcpConnection > 0); - x = comm_udp_sendto(theOutIcpConnection, - &S, sizeof(S), - sndbuf, strlen(sndbuf) + 1); - if (x < 0) - debug(27, 1) ("send_announce: FD %d: %s\n", theOutIcpConnection, - xstrerror()); -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/send-announce.cc Wed Feb 14 01:07:35 2007 @@ -0,0 +1,109 @@ + +/* + * $Id: send-announce.cc,v 1.1.2.1 2002/10/07 02:04:10 rbcollins Exp $ + * + * DEBUG: section 27 Cache Announcer + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; 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 IPH send_announce; + +void +start_announce(void *datanotused) +{ + if (0 == Config.onoff.announce) + return; + if (theOutIcpConnection < 0) + return; + ipcache_nbgethostbyname(Config.Announce.host, send_announce, NULL); + eventAdd("send_announce", start_announce, NULL, (double) Config.Announce.period, 1); +} + +static void +send_announce(const ipcache_addrs * ia, void *junk) +{ + LOCAL_ARRAY(char, tbuf, 256); + LOCAL_ARRAY(char, sndbuf, BUFSIZ); + struct sockaddr_in S; + char *host = Config.Announce.host; + char *file = NULL; + u_short port = Config.Announce.port; + int l; + int n; + int fd; + int x; + if (ia == NULL) { + debug(27, 1) ("send_announce: Unknown host '%s'\n", host); + return; + } + debug(27, 1) ("Sending Announcement to %s\n", host); + sndbuf[0] = '\0'; + snprintf(tbuf, 256, "cache_version SQUID/%s\n", version_string); + strcat(sndbuf, tbuf); + assert(Config.Sockaddr.http); + snprintf(tbuf, 256, "Running on %s %d %d\n", + getMyHostname(), + getMyPort(), + (int) Config.Port.icp); + strcat(sndbuf, tbuf); + if (Config.adminEmail) { + snprintf(tbuf, 256, "cache_admin: %s\n", Config.adminEmail); + strcat(sndbuf, tbuf); + } + snprintf(tbuf, 256, "generated %d [%s]\n", + (int) squid_curtime, + mkhttpdlogtime(&squid_curtime)); + strcat(sndbuf, tbuf); + l = strlen(sndbuf); + if ((file = Config.Announce.file) != NULL) { + fd = file_open(file, O_RDONLY | O_TEXT); + if (fd > -1 && (n = FD_READ_METHOD(fd, sndbuf + l, BUFSIZ - l - 1)) > 0) { + fd_bytes(fd, n, FD_READ); + l += n; + sndbuf[l] = '\0'; + file_close(fd); + } else { + debug(50, 1) ("send_announce: %s: %s\n", file, xstrerror()); + } + } + memset(&S, '\0', sizeof(S)); + S.sin_family = AF_INET; + S.sin_port = htons(port); + S.sin_addr = ia->in_addrs[0]; + assert(theOutIcpConnection > 0); + x = comm_udp_sendto(theOutIcpConnection, + &S, sizeof(S), + sndbuf, strlen(sndbuf) + 1); + if (x < 0) + debug(27, 1) ("send_announce: FD %d: %s\n", theOutIcpConnection, + xstrerror()); +} --- squid/src/unlinkd.c Wed Feb 14 01:07:35 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,200 +0,0 @@ - -/* - * $Id: unlinkd.c,v 1.9 2002/07/21 01:06:07 squidadm Exp $ - * - * DEBUG: section 2 Unlink Daemon - * AUTHOR: Duane Wessels - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; 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" - -#ifdef UNLINK_DAEMON - -/* This is the external unlinkd process */ - -#define UNLINK_BUF_LEN 1024 - -int -main(int argc, char *argv[]) -{ - char buf[UNLINK_BUF_LEN]; - char *t; - int x; - setbuf(stdin, NULL); - setbuf(stdout, NULL); - close(2); - open("/dev/null", O_RDWR); - while (fgets(buf, UNLINK_BUF_LEN, stdin)) { - if ((t = strchr(buf, '\n'))) - *t = '\0'; -#if USE_TRUNCATE - x = truncate(buf, 0); -#else - x = unlink(buf); -#endif - if (x < 0) - printf("ERR\n"); - else - printf("OK\n"); - } - exit(0); -} - -#else /* UNLINK_DAEMON */ - -/* This code gets linked to Squid */ - -static int unlinkd_wfd = -1; -static int unlinkd_rfd = -1; - -#define UNLINKD_QUEUE_LIMIT 20 - -void -unlinkdUnlink(const char *path) -{ - char buf[MAXPATHLEN]; - int l; - int x; - static int queuelen = 0; - if (unlinkd_wfd < 0) { - debug_trap("unlinkdUnlink: unlinkd_wfd < 0"); - safeunlink(path, 0); - return; - } - /* - * If the queue length is greater than our limit, then - * we pause for up to 100ms, hoping that unlinkd - * has some feedback for us. Maybe it just needs a slice - * of the CPU's time. - */ - if (queuelen >= UNLINKD_QUEUE_LIMIT) { - struct timeval to; - fd_set R; - FD_ZERO(&R); - FD_SET(unlinkd_rfd, &R); - to.tv_sec = 0; - to.tv_usec = 100000; - select(unlinkd_rfd + 1, &R, NULL, NULL, &to); - } - /* - * If there is at least one outstanding unlink request, then - * try to read a response. If there's nothing to read we'll - * get an EWOULDBLOCK or whatever. If we get a response, then - * decrement the queue size by the number of newlines read. - */ - if (queuelen > 0) { - int x; - int i; - char rbuf[512]; - x = read(unlinkd_rfd, rbuf, 511); - if (x > 0) { - rbuf[x] = '\0'; - for (i = 0; i < x; i++) - if ('\n' == rbuf[i]) - queuelen--; - assert(queuelen >= 0); - } - } - l = strlen(path); - assert(l < MAXPATHLEN); - xstrncpy(buf, path, MAXPATHLEN); - buf[l++] = '\n'; - x = write(unlinkd_wfd, buf, l); - if (x < 0) { - debug(2, 1) ("unlinkdUnlink: write FD %d failed: %s\n", - unlinkd_wfd, xstrerror()); - safeunlink(path, 0); - return; - } else if (x != l) { - debug(2, 1) ("unlinkdUnlink: FD %d only wrote %d of %d bytes\n", - unlinkd_wfd, x, l); - safeunlink(path, 0); - return; - } - statCounter.unlink.requests++; - queuelen++; -} - -void -unlinkdClose(void) -{ - if (unlinkd_wfd < 0) - return; - debug(2, 1) ("Closing unlinkd pipe on FD %d\n", unlinkd_wfd); - file_close(unlinkd_wfd); - if (unlinkd_wfd != unlinkd_rfd) - file_close(unlinkd_rfd); - unlinkd_wfd = -1; - unlinkd_rfd = -1; -} - -void -unlinkdInit(void) -{ - int x; - const char *args[2]; - struct timeval slp; - args[0] = "(unlinkd)"; - args[1] = NULL; -#if USE_POLL && defined(_SQUID_OSF_) - /* pipes and poll() don't get along on DUNIX -DW */ - x = ipcCreate(IPC_STREAM, -#else - /* We currently need to use FIFO.. see below */ - x = ipcCreate(IPC_FIFO, -#endif - Config.Program.unlinkd, - args, - "unlinkd", - &unlinkd_rfd, - &unlinkd_wfd); - if (x < 0) - fatal("Failed to create unlinkd subprocess"); - slp.tv_sec = 0; - slp.tv_usec = 250000; - select(0, NULL, NULL, NULL, &slp); - fd_note(unlinkd_wfd, "squid -> unlinkd"); - fd_note(unlinkd_rfd, "unlinkd -> squid"); - commSetTimeout(unlinkd_rfd, -1, NULL, NULL); - commSetTimeout(unlinkd_wfd, -1, NULL, NULL); - /* - * unlinkd_rfd should already be non-blocking because of - * ipcCreate. We change unlinkd_wfd to blocking mode because - * we never want to lose an unlink request, and we don't have - * code to retry if we get EWOULDBLOCK. Unfortunately, we can - * do this only for the IPC_FIFO case. - */ - assert(fd_table[unlinkd_rfd].flags.nonblocking); - if (FD_PIPE == fd_table[unlinkd_wfd].type) - commUnsetNonBlocking(unlinkd_wfd); - debug(2, 1) ("Unlinkd pipe opened on FD %d\n", unlinkd_wfd); -} - -#endif /* ndef UNLINK_DAEMON */ --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/unlinkd.cc Wed Feb 14 01:07:35 2007 @@ -0,0 +1,200 @@ + +/* + * $Id: unlinkd.cc,v 1.1.2.1 2002/10/07 02:04:10 rbcollins Exp $ + * + * DEBUG: section 2 Unlink Daemon + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; 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" + +#ifdef UNLINK_DAEMON + +/* This is the external unlinkd process */ + +#define UNLINK_BUF_LEN 1024 + +int +main(int argc, char *argv[]) +{ + char buf[UNLINK_BUF_LEN]; + char *t; + int x; + setbuf(stdin, NULL); + setbuf(stdout, NULL); + close(2); + open("/dev/null", O_RDWR); + while (fgets(buf, UNLINK_BUF_LEN, stdin)) { + if ((t = strchr(buf, '\n'))) + *t = '\0'; +#if USE_TRUNCATE + x = truncate(buf, 0); +#else + x = unlink(buf); +#endif + if (x < 0) + printf("ERR\n"); + else + printf("OK\n"); + } + exit(0); +} + +#else /* UNLINK_DAEMON */ + +/* This code gets linked to Squid */ + +static int unlinkd_wfd = -1; +static int unlinkd_rfd = -1; + +#define UNLINKD_QUEUE_LIMIT 20 + +void +unlinkdUnlink(const char *path) +{ + char buf[MAXPATHLEN]; + int l; + int x; + static int queuelen = 0; + if (unlinkd_wfd < 0) { + debug_trap("unlinkdUnlink: unlinkd_wfd < 0"); + safeunlink(path, 0); + return; + } + /* + * If the queue length is greater than our limit, then + * we pause for up to 100ms, hoping that unlinkd + * has some feedback for us. Maybe it just needs a slice + * of the CPU's time. + */ + if (queuelen >= UNLINKD_QUEUE_LIMIT) { + struct timeval to; + fd_set R; + FD_ZERO(&R); + FD_SET(unlinkd_rfd, &R); + to.tv_sec = 0; + to.tv_usec = 100000; + select(unlinkd_rfd + 1, &R, NULL, NULL, &to); + } + /* + * If there is at least one outstanding unlink request, then + * try to read a response. If there's nothing to read we'll + * get an EWOULDBLOCK or whatever. If we get a response, then + * decrement the queue size by the number of newlines read. + */ + if (queuelen > 0) { + int x; + int i; + char rbuf[512]; + x = read(unlinkd_rfd, rbuf, 511); + if (x > 0) { + rbuf[x] = '\0'; + for (i = 0; i < x; i++) + if ('\n' == rbuf[i]) + queuelen--; + assert(queuelen >= 0); + } + } + l = strlen(path); + assert(l < MAXPATHLEN); + xstrncpy(buf, path, MAXPATHLEN); + buf[l++] = '\n'; + x = write(unlinkd_wfd, buf, l); + if (x < 0) { + debug(2, 1) ("unlinkdUnlink: write FD %d failed: %s\n", + unlinkd_wfd, xstrerror()); + safeunlink(path, 0); + return; + } else if (x != l) { + debug(2, 1) ("unlinkdUnlink: FD %d only wrote %d of %d bytes\n", + unlinkd_wfd, x, l); + safeunlink(path, 0); + return; + } + statCounter.unlink.requests++; + queuelen++; +} + +void +unlinkdClose(void) +{ + if (unlinkd_wfd < 0) + return; + debug(2, 1) ("Closing unlinkd pipe on FD %d\n", unlinkd_wfd); + file_close(unlinkd_wfd); + if (unlinkd_wfd != unlinkd_rfd) + file_close(unlinkd_rfd); + unlinkd_wfd = -1; + unlinkd_rfd = -1; +} + +void +unlinkdInit(void) +{ + int x; + const char *args[2]; + struct timeval slp; + args[0] = "(unlinkd)"; + args[1] = NULL; +#if USE_POLL && defined(_SQUID_OSF_) + /* pipes and poll() don't get along on DUNIX -DW */ + x = ipcCreate(IPC_STREAM, +#else + /* We currently need to use FIFO.. see below */ + x = ipcCreate(IPC_FIFO, +#endif + Config.Program.unlinkd, + args, + "unlinkd", + &unlinkd_rfd, + &unlinkd_wfd); + if (x < 0) + fatal("Failed to create unlinkd subprocess"); + slp.tv_sec = 0; + slp.tv_usec = 250000; + select(0, NULL, NULL, NULL, &slp); + fd_note(unlinkd_wfd, "squid -> unlinkd"); + fd_note(unlinkd_rfd, "unlinkd -> squid"); + commSetTimeout(unlinkd_rfd, -1, NULL, NULL); + commSetTimeout(unlinkd_wfd, -1, NULL, NULL); + /* + * unlinkd_rfd should already be non-blocking because of + * ipcCreate. We change unlinkd_wfd to blocking mode because + * we never want to lose an unlink request, and we don't have + * code to retry if we get EWOULDBLOCK. Unfortunately, we can + * do this only for the IPC_FIFO case. + */ + assert(fd_table[unlinkd_rfd].flags.nonblocking); + if (FD_PIPE == fd_table[unlinkd_wfd].type) + commUnsetNonBlocking(unlinkd_wfd); + debug(2, 1) ("Unlinkd pipe opened on FD %d\n", unlinkd_wfd); +} + +#endif /* ndef UNLINK_DAEMON */ --- squid/src/urn.c Wed Feb 14 01:07:35 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,360 +0,0 @@ - -/* - * $Id: urn.c,v 1.18.2.1 2002/10/04 07:07:29 rbcollins Exp $ - * - * DEBUG: section 52 URN Parsing - * AUTHOR: Kostas Anagnostakis - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; 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" -#include "StoreClient.h" -#include "Store.h" - -#define URN_REQBUF_SZ 4096 - -typedef struct { - StoreEntry *entry; - store_client *sc; - StoreEntry *urlres_e; - request_t *request; - request_t *urlres_r; - struct { - unsigned int force_menu:1; - } flags; - char reqbuf[URN_REQBUF_SZ]; - int reqofs; -} 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; - -static 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; -} - -CBDATA_TYPE(UrnState); -void -urnStart(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; - StoreIOBuffer tempBuffer = EMPTYIOBUFFER; - debug(52, 3) ("urnStart: '%s'\n", storeUrl(e)); - CBDATA_INIT_TYPE(UrnState); - urnState = cbdataAlloc(UrnState); - urnState->entry = e; - urnState->request = requestLink(r); - 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); - urnState->sc = storeClientListAdd(urlres_e, urnState); - fwdStart(-1, urlres_e, urlres_r); - } else { - storeLockObject(urlres_e); - urnState->sc = storeClientListAdd(urlres_e, urnState); - } - urnState->urlres_e = urlres_e; - urnState->urlres_r = requestLink(urlres_r); - urnState->reqofs = 0; - tempBuffer.offset = urnState->reqofs; - tempBuffer.length = URN_REQBUF_SZ; - tempBuffer.data = urnState->reqbuf; - storeClientCopy(urnState->sc, urlres_e, - tempBuffer, - urnHandleReply, - urnState); -} - -static int -url_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 void -urnHandleReply(void *data, StoreIOBuffer result) -{ - 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; - http_version_t version; - char *buf = urnState->reqbuf; - StoreIOBuffer tempBuffer; - - debug(52, 3) ("urnHandleReply: Called with size=%u.\n", result.length); - if (EBIT_TEST(urlres_e->flags, ENTRY_ABORTED)) { - goto error; - } - if (result.length == 0) { - goto error; - } else if (result.flags.error < 0) { - goto error; - } - /* Update reqofs to point to where in the buffer we'd be */ - urnState->reqofs += result.length; - - /* Handle reqofs being bigger than normal */ - if (urnState->reqofs >= URN_REQBUF_SZ) { - goto error; - } - /* If we haven't received the entire object (urn), copy more */ - if (urlres_e->store_status == STORE_PENDING && - urnState->reqofs < URN_REQBUF_SZ) { - tempBuffer.offset = urnState->reqofs; - tempBuffer.length = URN_REQBUF_SZ; - tempBuffer.data = urnState->reqbuf + urnState->reqofs; - storeClientCopy(urnState->sc, urlres_e, - tempBuffer, - urnHandleReply, - urnState); - return; - } - /* we know its STORE_OK */ - k = headersEnd(buf, urnState->reqofs); - if (0 == k) { - debug(52, 1) ("urnHandleReply: didn't find end-of-headers for %s\n", - storeUrl(e)); - goto error; - } - s = buf + k; - assert(urlres_e->mem_obj->reply); - httpReplyParse(urlres_e->mem_obj->reply, buf, k); - 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); - goto error; - } - 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); - goto error; - } - min_u = urnFindMinRtt(urls, urnState->request->method, NULL); - qsort(urls, urlcnt, sizeof(*urls), url_entry_sort); - storeBuffer(e); - memBufDefInit(&mb); - memBufPrintf(&mb, - "Select URL for %s\n" - "\n" - "

Select URL for %s

\n" - "\n", storeUrl(e), storeUrl(e)); - for (i = 0; i < urlcnt; i++) { - u = &urls[i]; - debug(52, 3) ("URL {%s}\n", u->url); - memBufPrintf(&mb, - "", u->url, u->url); - if (urls[i].rtt > 0) - memBufPrintf(&mb, - "", u->rtt); - else - memBufPrintf(&mb, ""); - memBufPrintf(&mb, - "\n", u->flags.cached ? " [cached]" : " "); - } - memBufPrintf(&mb, - "
%s%4d msUnknown%s
" - "
\n" - "
\n" - "Generated by %s@%s\n" - "
\n", - full_appname_string, getMyHostname()); - rep = e->mem_obj->reply; - httpReplyReset(rep); - httpBuildVersion(&version, 1, 0); - httpReplySetHeaders(rep, version, 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); - 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(urnState->sc, urlres_e, urnState); - error: - 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; -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/urn.cc Wed Feb 14 01:07:35 2007 @@ -0,0 +1,403 @@ + +/* + * $Id: urn.cc,v 1.1.2.1 2002/10/07 02:04:10 rbcollins Exp $ + * + * DEBUG: section 52 URN Parsing + * AUTHOR: Kostas Anagnostakis + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; 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" +#include "StoreClient.h" +#include "Store.h" + +#define URN_REQBUF_SZ 4096 + +class UrnState : public StoreClient { +public: + void created (_StoreEntry *newEntry); + void *operator new (unsigned int byteCount); + void operator delete (void *address); + void start (request_t *, StoreEntry *); + char *getHost (String &urlpath); + + + StoreEntry *entry; + store_client *sc; + StoreEntry *urlres_e; + request_t *request; + request_t *urlres_r; + struct { + unsigned int force_menu:1; + } flags; + char reqbuf[URN_REQBUF_SZ]; + int reqofs; +}; + +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; + +CBDATA_TYPE(UrnState); +void * +UrnState::operator new (unsigned int byteCount) +{ + /* derived classes with different sizes must implement their own new */ + assert (byteCount == sizeof (UrnState)); + CBDATA_INIT_TYPE(UrnState); + return cbdataAlloc(UrnState); + +} + +void +UrnState::operator delete (void *address) +{ + cbdataFree ((UrnState *)address); +} + +void +UrnState::created (_StoreEntry *newEntry) +{ +} + +static 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; +} + +char * +UrnState::getHost (String &urlpath) +{ + char * result; + char const *t; + if ((t = strChr(urlpath, ':')) != NULL) { + strSet(urlpath, t, '\0'); + result = xstrdup(strBuf(urlpath)); + strSet(urlpath, t, ':'); + } else { + result = xstrdup(strBuf(urlpath)); + } + return result; +} + +void +UrnState::setUriResFromRequest(request_t *r) +{ +} + +void +UrnState::start(request_t * r, StoreEntry * e) +{ + LOCAL_ARRAY(char, urlres, 4096); + char *host; + ErrorState *err; + StoreIOBuffer tempBuffer = EMPTYIOBUFFER; + debug(52, 3) ("urnStart: '%s'\n", storeUrl(e)); + entry = e; + request = requestLink(r); + storeLockObject(entry); + if (strncasecmp(strBuf(r->urlpath), "menu.", 5) == 0) { + char *new_path = xstrdup(strBuf(r->urlpath) + 5); + flags.force_menu = 1; + stringReset(&r->urlpath, new_path); + xfree(new_path); + } + host = getHost (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; + } + requestLink(urlres_r); + 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); + sc = storeClientListAdd(urlres_e, this); + fwdStart(-1, urlres_e, urlres_r); + } else { + storeLockObject(urlres_e); + sc = storeClientListAdd(urlres_e, this); + } + reqofs = 0; + tempBuffer.offset = reqofs; + tempBuffer.length = URN_REQBUF_SZ; + tempBuffer.data = reqbuf; + storeClientCopy(sc, urlres_e, + tempBuffer, + urnHandleReply, + this); +} + +void +urnStart(request_t * r, StoreEntry * e) +{ + UrnState *anUrn = new UrnState(); + anUrn->start (r, e); +} + +static int +url_entry_sort(const void *A, const void *B) +{ + const url_entry *u1 = (const url_entry *)A; + const url_entry *u2 = (const url_entry *)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 void +urnHandleReply(void *data, StoreIOBuffer result) +{ + UrnState *urnState = static_cast(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; + http_version_t version; + char *buf = urnState->reqbuf; + StoreIOBuffer tempBuffer; + + debug(52, 3) ("urnHandleReply: Called with size=%u.\n", result.length); + if (EBIT_TEST(urlres_e->flags, ENTRY_ABORTED)) { + goto error; + } + if (result.length == 0) { + goto error; + } else if (result.flags.error < 0) { + goto error; + } + /* Update reqofs to point to where in the buffer we'd be */ + urnState->reqofs += result.length; + + /* Handle reqofs being bigger than normal */ + if (urnState->reqofs >= URN_REQBUF_SZ) { + goto error; + } + /* If we haven't received the entire object (urn), copy more */ + if (urlres_e->store_status == STORE_PENDING && + urnState->reqofs < URN_REQBUF_SZ) { + tempBuffer.offset = urnState->reqofs; + tempBuffer.length = URN_REQBUF_SZ; + tempBuffer.data = urnState->reqbuf + urnState->reqofs; + storeClientCopy(urnState->sc, urlres_e, + tempBuffer, + urnHandleReply, + urnState); + return; + } + /* we know its STORE_OK */ + k = headersEnd(buf, urnState->reqofs); + if (0 == k) { + debug(52, 1) ("urnHandleReply: didn't find end-of-headers for %s\n", + storeUrl(e)); + goto error; + } + s = buf + k; + assert(urlres_e->mem_obj->reply); + httpReplyParse(urlres_e->mem_obj->reply, buf, k); + 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); + goto error; + } + 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); + goto error; + } + min_u = urnFindMinRtt(urls, urnState->request->method, NULL); + qsort(urls, urlcnt, sizeof(*urls), url_entry_sort); + storeBuffer(e); + memBufDefInit(&mb); + memBufPrintf(&mb, + "Select URL for %s\n" + "\n" + "

Select URL for %s

\n" + "\n", storeUrl(e), storeUrl(e)); + for (i = 0; i < urlcnt; i++) { + u = &urls[i]; + debug(52, 3) ("URL {%s}\n", u->url); + memBufPrintf(&mb, + "", u->url, u->url); + if (urls[i].rtt > 0) + memBufPrintf(&mb, + "", u->rtt); + else + memBufPrintf(&mb, ""); + memBufPrintf(&mb, + "\n", u->flags.cached ? " [cached]" : " "); + } + memBufPrintf(&mb, + "
%s%4d msUnknown%s
" + "
\n" + "
\n" + "Generated by %s@%s\n" + "
\n", + full_appname_string, getMyHostname()); + rep = e->mem_obj->reply; + httpReplyReset(rep); + httpBuildVersion(&version, 1, 0); + httpReplySetHeaders(rep, version, 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); + 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(urnState->sc, urlres_e, urnState); + error: + storeUnlockObject(urlres_e); + storeUnlockObject(urnState->entry); + requestUnlink(urnState->request); + requestUnlink(urnState->urlres_r); + delete 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 = (url_entry *)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 = (url_entry *)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; +}