---------------------
PatchSet 3
Date: 2000/01/26 03:23:09
Author: hno
Branch: NLANR
Tag: s2_2_s5
Log:
Imported Squid-2.2.STABLE5 sources
Members:
CONTRIBUTORS:1.1.1.1->1.1.1.2
CREDITS:1.1.1.1->1.1.1.2
ChangeLog:1.1.1.1->1.1.1.2
acconfig.h:1.1.1.1->1.1.1.2
configure:1.1.1.1->1.1.1.2
configure.in:1.1.1.1->1.1.1.2
makefile.in:1.1.1.1->1.1.1.2
auth_modules/SMB/COPYING-2.0:1.1->1.1.1.1
auth_modules/SMB/Changelog:1.1->1.1.1.1
auth_modules/SMB/Makefile:1.1->1.1.1.1
auth_modules/SMB/README:1.1.1.1->1.1.1.2
auth_modules/SMB/smb_auth.c:1.1->1.1.1.1
auth_modules/SMB/smb_auth.sh:1.1->1.1.1.1
auth_modules/getpwnam/Makefile.in:1.1->1.1.1.1
auth_modules/getpwnam/getpwnam_auth.c:1.1->1.1.1.1
cfgaux/config.guess:1.1.1.1->1.1.1.2
cfgaux/config.sub:1.1.1.1->1.1.1.2
doc/Programming-Guide/Makefile:1.1->1.1.1.1
doc/Programming-Guide/prog-guide.sgml:1.1->1.1.1.1
errors/Bulgarian/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Bulgarian/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Bulgarian/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Bulgarian/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Czech/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Czech/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Czech/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Czech/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Dutch/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Dutch/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Dutch/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Dutch/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/English/ERR_FTP_FAILURE:1.1.1.1->1.1.1.2
errors/English/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/English/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/English/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/English/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Estonian/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Estonian/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Estonian/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Estonian/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Estonian/ERR_ZERO_SIZE_OBJECT:1.1.1.1->1.1.1.2
errors/French/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/French/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/French/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/French/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/German/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/German/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/German/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/German/ERR_READ_TIMEOUT:1.1.1.1->1.1.1.2
errors/German/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Hungarian/ERR_CANNOT_FORWARD:1.1.1.1->1.1.1.2
errors/Hungarian/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Hungarian/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Hungarian/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Hungarian/ERR_ONLY_IF_CACHED_MISS:1.1.1.1->1.1.1.2
errors/Hungarian/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Italian/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Italian/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Italian/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Italian/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Japanese/ERR_ACCESS_DENIED:1.1->1.1.1.1
errors/Japanese/ERR_CACHE_ACCESS_DENIED:1.1->1.1.1.1
errors/Japanese/ERR_CACHE_MGR_ACCESS_DENIED:1.1->1.1.1.1
errors/Japanese/ERR_CANNOT_FORWARD:1.1->1.1.1.1
errors/Japanese/ERR_CONNECT_FAIL:1.1->1.1.1.1
errors/Japanese/ERR_DNS_FAIL:1.1->1.1.1.1
errors/Japanese/ERR_FORWARDING_DENIED:1.1->1.1.1.1
errors/Japanese/ERR_FTP_DISABLED:1.1->1.1.1.1
errors/Japanese/ERR_FTP_FAILURE:1.1->1.1.1.1
errors/Japanese/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Japanese/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Japanese/ERR_FTP_PUT_CREATED:1.1->1.1.1.1
errors/Japanese/ERR_FTP_PUT_ERROR:1.1->1.1.1.1
errors/Japanese/ERR_FTP_PUT_MODIFIED:1.1->1.1.1.1
errors/Japanese/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Japanese/ERR_INVALID_REQ:1.1->1.1.1.1
errors/Japanese/ERR_INVALID_URL:1.1->1.1.1.1
errors/Japanese/ERR_LIFETIME_EXP:1.1->1.1.1.1
errors/Japanese/ERR_NO_RELAY:1.1->1.1.1.1
errors/Japanese/ERR_ONLY_IF_CACHED_MISS:1.1->1.1.1.1
errors/Japanese/ERR_READ_ERROR:1.1->1.1.1.1
errors/Japanese/ERR_READ_TIMEOUT:1.1->1.1.1.1
errors/Japanese/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Japanese/ERR_SOCKET_FAILURE:1.1->1.1.1.1
errors/Japanese/ERR_UNSUP_REQ:1.1->1.1.1.1
errors/Japanese/ERR_URN_RESOLVE:1.1->1.1.1.1
errors/Japanese/ERR_WRITE_ERROR:1.1->1.1.1.1
errors/Japanese/ERR_ZERO_SIZE_OBJECT:1.1->1.1.1.1
errors/Japanese/README:1.1->1.1.1.1
errors/Japanese/generic:1.1->1.1.1.1
errors/Polish/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Polish/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Polish/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Polish/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Portuguese/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Portuguese/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Portuguese/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Portuguese/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Russian-1251/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Russian-1251/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Russian-1251/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Russian-1251/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Russian-koi8-r/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Russian-koi8-r/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Russian-koi8-r/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Russian-koi8-r/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Slovak/ERR_ACCESS_DENIED:1.1->1.1.1.1
errors/Slovak/ERR_CACHE_ACCESS_DENIED:1.1->1.1.1.1
errors/Slovak/ERR_CACHE_MGR_ACCESS_DENIED:1.1->1.1.1.1
errors/Slovak/ERR_CANNOT_FORWARD:1.1->1.1.1.1
errors/Slovak/ERR_CONNECT_FAIL:1.1->1.1.1.1
errors/Slovak/ERR_DNS_FAIL:1.1->1.1.1.1
errors/Slovak/ERR_FORWARDING_DENIED:1.1->1.1.1.1
errors/Slovak/ERR_FTP_DISABLED:1.1->1.1.1.1
errors/Slovak/ERR_FTP_FAILURE:1.1->1.1.1.1
errors/Slovak/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Slovak/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Slovak/ERR_FTP_PUT_CREATED:1.1->1.1.1.1
errors/Slovak/ERR_FTP_PUT_ERROR:1.1->1.1.1.1
errors/Slovak/ERR_FTP_PUT_MODIFIED:1.1->1.1.1.1
errors/Slovak/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Slovak/ERR_INVALID_REQ:1.1->1.1.1.1
errors/Slovak/ERR_INVALID_URL:1.1->1.1.1.1
errors/Slovak/ERR_LIFETIME_EXP:1.1->1.1.1.1
errors/Slovak/ERR_NO_RELAY:1.1->1.1.1.1
errors/Slovak/ERR_ONLY_IF_CACHED_MISS:1.1->1.1.1.1
errors/Slovak/ERR_READ_ERROR:1.1->1.1.1.1
errors/Slovak/ERR_READ_TIMEOUT:1.1->1.1.1.1
errors/Slovak/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Slovak/ERR_SOCKET_FAILURE:1.1->1.1.1.1
errors/Slovak/ERR_UNSUP_REQ:1.1->1.1.1.1
errors/Slovak/ERR_URN_RESOLVE:1.1->1.1.1.1
errors/Slovak/ERR_WRITE_ERROR:1.1->1.1.1.1
errors/Slovak/ERR_ZERO_SIZE_OBJECT:1.1->1.1.1.1
errors/Slovak/README:1.1->1.1.1.1
errors/Slovak/generic:1.1->1.1.1.1
errors/Spanish/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Spanish/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Spanish/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Spanish/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_ACCESS_DENIED:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_CACHE_ACCESS_DENIED:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_CACHE_MGR_ACCESS_DENIED:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_CANNOT_FORWARD:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_CONNECT_FAIL:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_DNS_FAIL:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_FORWARDING_DENIED:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_FTP_DISABLED:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_FTP_FAILURE:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_FTP_PUT_CREATED:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_FTP_PUT_ERROR:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_FTP_PUT_MODIFIED:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_INVALID_REQ:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_INVALID_URL:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_LIFETIME_EXP:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_NO_RELAY:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_ONLY_IF_CACHED_MISS:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_READ_ERROR:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_READ_TIMEOUT:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_SHUTTING_DOWN:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_SOCKET_FAILURE:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_UNSUP_REQ:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_URN_RESOLVE:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_WRITE_ERROR:1.1->1.1.1.1
errors/Traditional_Chinese/ERR_ZERO_SIZE_OBJECT:1.1->1.1.1.1
errors/Traditional_Chinese/README:1.1->1.1.1.1
errors/Traditional_Chinese/generic:1.1->1.1.1.1
errors/Turkish/ERR_FTP_FORBIDDEN:1.1->1.1.1.1
errors/Turkish/ERR_FTP_NOT_FOUND:1.1->1.1.1.1
errors/Turkish/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1
errors/Turkish/ERR_SHUTTING_DOWN:1.1->1.1.1.1
icons/Makefile.in:1.1.1.1->1.1.1.2
icons/anthony-binhex.gif:1.1->1.1.1.1
icons/anthony-bomb.gif:1.1->1.1.1.1
icons/anthony-box.gif:1.1->1.1.1.1
icons/anthony-box2.gif:1.1->1.1.1.1
icons/anthony-c.gif:1.1->1.1.1.1
icons/anthony-compressed.gif:1.1->1.1.1.1
icons/anthony-dir.gif:1.1->1.1.1.1
icons/anthony-dirup.gif:1.1->1.1.1.1
icons/anthony-dvi.gif:1.1->1.1.1.1
icons/anthony-f.gif:1.1->1.1.1.1
icons/anthony-image.gif:1.1->1.1.1.1
icons/anthony-image2.gif:1.1->1.1.1.1
icons/anthony-layout.gif:1.1->1.1.1.1
icons/anthony-link.gif:1.1->1.1.1.1
icons/anthony-movie.gif:1.1->1.1.1.1
icons/anthony-pdf.gif:1.1->1.1.1.1
icons/anthony-portal.gif:1.1->1.1.1.1
icons/anthony-ps.gif:1.1->1.1.1.1
icons/anthony-quill.gif:1.1->1.1.1.1
icons/anthony-script.gif:1.1->1.1.1.1
icons/anthony-sound.gif:1.1->1.1.1.1
icons/anthony-tar.gif:1.1->1.1.1.1
icons/anthony-tex.gif:1.1->1.1.1.1
icons/anthony-text.gif:1.1->1.1.1.1
icons/anthony-unknown.gif:1.1->1.1.1.1
icons/anthony-xbm.gif:1.1->1.1.1.1
icons/anthony-xpm.gif:1.1->1.1.1.1
include/GNUregex.h:1.1.1.1->1.1.1.2
include/autoconf.h.in:1.1.1.1->1.1.1.2
include/cache_snmp.h:1.1.1.1->1.1.1.2
include/config.h.in:1.1.1.1->1.1.1.2
include/snmp_debug.h:1.1.1.1->1.1.1.2
include/util.h:1.1.1.1->1.1.1.2
include/version.h:1.1.1.1->1.1.1.2
lib/hash.c:1.1.1.1->1.1.1.2
lib/inet_ntoa.c:1.1->1.1.1.1
lib/radix.c:1.1.1.1->1.1.1.2
lib/rfc1123.c:1.1.1.1->1.1.1.2
lib/safe_inet_addr.c:1.1.1.1->1.1.1.2
lib/snprintf.c:1.1.1.1->1.1.1.2
lib/util.c:1.1.1.1->1.1.1.2
scripts/RunAccel.in:1.1.1.1->1.1.1.2
scripts/RunCache.in:1.1.1.1->1.1.1.2
scripts/convert.configure.to.os2:1.1->1.1.1.1
scripts/udp-banger.pl:1.1.1.1->1.1.1.2
snmplib/parse.c:1.1.1.1->1.1.1.2
snmplib/snmplib_debug.c:1.1.1.1->1.1.1.2
src/CacheDigest.c:1.1.1.1->1.1.1.2
src/HttpHdrCc.c:1.1.1.1->1.1.1.2
src/HttpHdrContRange.c:1.1.1.1->1.1.1.2
src/HttpHdrExtField.c:1.1.1.1->1.1.1.2
src/HttpHdrRange.c:1.1.1.1->1.1.1.2
src/HttpHeader.c:1.1.1.1->1.1.1.2
src/HttpHeaderTools.c:1.1.1.1->1.1.1.2
src/HttpReply.c:1.1.1.1->1.1.1.2
src/HttpRequest.c:1.1.1.1->1.1.1.2
src/HttpStatusLine.c:1.1.1.1->1.1.1.2
src/Makefile.in:1.1.1.1->1.1.1.2
src/MemBuf.c:1.1.1.1->1.1.1.2
src/MemPool.c:1.1.1.1->1.1.1.2
src/Packer.c:1.1.1.1->1.1.1.2
src/StatHist.c:1.1.1.1->1.1.1.2
src/access_log.c:1.1.1.1->1.1.1.2
src/acl.c:1.1.1.1->1.1.1.2
src/aiops.c:1.1.1.1->1.1.1.2
src/asn.c:1.1.1.1->1.1.1.2
src/async_io.c:1.1.1.1->1.1.1.2
src/authenticate.c:1.1.1.1->1.1.1.2
src/cache_cf.c:1.1.1.1->1.1.1.2
src/cache_manager.c:1.1.1.1->1.1.1.2
src/cachemgr.c:1.1.1.1->1.1.1.2
src/cbdata.c:1.1.1.1->1.1.1.2
src/cf.data.pre:1.1.1.1->1.1.1.2
src/cf_gen.c:1.1.1.1->1.1.1.2
src/client.c:1.1.1.1->1.1.1.2
src/client_db.c:1.1.1.1->1.1.1.2
src/client_side.c:1.1.1.1->1.1.1.2
src/comm.c:1.1.1.1->1.1.1.2
src/comm_select.c:1.1.1.1->1.1.1.2
src/debug.c:1.1.1.1->1.1.1.2
src/defines.h:1.1.1.1->1.1.1.2
src/delay_pools.c:1.1.1.1->1.1.1.2
src/disk.c:1.1.1.1->1.1.1.2
src/dns.c:1.1.1.1->1.1.1.2
src/dnsserver.c:1.1.1.1->1.1.1.2
src/enums.h:1.1.1.1->1.1.1.2
src/errorpage.c:1.1.1.1->1.1.1.2
src/event.c:1.1.1.1->1.1.1.2
src/fd.c:1.1.1.1->1.1.1.2
src/forward.c:1.1.1.1->1.1.1.2
src/fqdncache.c:1.1.1.1->1.1.1.2
src/ftp.c:1.1.1.1->1.1.1.2
src/globals.h:1.1.1.1->1.1.1.2
src/gopher.c:1.1.1.1->1.1.1.2
src/helper.c:1.1.1.1->1.1.1.2
src/http.c:1.1.1.1->1.1.1.2
src/icmp.c:1.1.1.1->1.1.1.2
src/icp_v2.c:1.1.1.1->1.1.1.2
src/icp_v3.c:1.1.1.1->1.1.1.2
src/ident.c:1.1.1.1->1.1.1.2
src/internal.c:1.1.1.1->1.1.1.2
src/ipc.c:1.1.1.1->1.1.1.2
src/ipcache.c:1.1.1.1->1.1.1.2
src/leakfinder.c:1.1->1.1.1.1
src/main.c:1.1.1.1->1.1.1.2
src/mem.c:1.1.1.1->1.1.1.2
src/mib.txt:1.1.1.1->1.1.1.2
src/mime.c:1.1.1.1->1.1.1.2
src/mime.conf:1.1.1.1->1.1.1.2
src/neighbors.c:1.1.1.1->1.1.1.2
src/net_db.c:1.1.1.1->1.1.1.2
src/pconn.c:1.1.1.1->1.1.1.2
src/peer_digest.c:1.1.1.1->1.1.1.2
src/peer_select.c:1.1.1.1->1.1.1.2
src/pinger.c:1.1.1.1->1.1.1.2
src/protos.h:1.1.1.1->1.1.1.2
src/pump.c:1.1.1.1->1.1.1.2
src/redirect.c:1.1.1.1->1.1.1.2
src/refresh.c:1.1.1.1->1.1.1.2
src/send-announce.c:1.1.1.1->1.1.1.2
src/snmp_agent.c:1.1.1.1->1.1.1.2
src/snmp_core.c:1.1.1.1->1.1.1.2
src/squid.h:1.1.1.1->1.1.1.2
src/ssl.c:1.1.1.1->1.1.1.2
src/stat.c:1.1.1.1->1.1.1.2
src/stmem.c:1.1.1.1->1.1.1.2
src/store.c:1.1.1.1->1.1.1.2
src/store_clean.c:1.1.1.1->1.1.1.2
src/store_client.c:1.1.1.1->1.1.1.2
src/store_digest.c:1.1.1.1->1.1.1.2
src/store_dir.c:1.1.1.1->1.1.1.2
src/store_key_md5.c:1.1.1.1->1.1.1.2
src/store_rebuild.c:1.1.1.1->1.1.1.2
src/store_swapin.c:1.1.1.1->1.1.1.2
src/store_swapout.c:1.1.1.1->1.1.1.2
src/structs.h:1.1.1.1->1.1.1.2
src/tools.c:1.1.1.1->1.1.1.2
src/typedefs.h:1.1.1.1->1.1.1.2
src/unlinkd.c:1.1.1.1->1.1.1.2
src/url.c:1.1.1.1->1.1.1.2
src/urn.c:1.1.1.1->1.1.1.2
src/useragent.c:1.1.1.1->1.1.1.2
src/wais.c:1.1.1.1->1.1.1.2
src/whois.c:1.1.1.1->1.1.1.2
test-suite/tcp-banger2.c:1.1.1.1->1.1.1.2
test-suite/tcp-banger3.c:1.1.1.1->1.1.1.2
Index: squid/CONTRIBUTORS
===================================================================
RCS file: /cvsroot/squid-sf//squid/CONTRIBUTORS,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/CONTRIBUTORS 26 Jan 2000 03:21:46 -0000 1.1.1.1
+++ squid/CONTRIBUTORS 26 Jan 2000 03:23:09 -0000 1.1.1.2
@@ -68,6 +68,7 @@
Eric Stern
-This might be caused by an FTP URL with an absolute path (which does
-not comply with RFC 1738). If this is the cause, then the file
-can be found at %B.
-Bei des Versuches, Daten vom Netzwerk zu lesen, mußte zu lange
+Bei dem Versuch Daten vom Netzwerk zu lesen, mußte zu lange
gewartet werden (timeout).
Das Netzwerk oder der Server könnten deaktiviert oder
überlastet sein. Bitte versuchen Sie Ihre Anfrage erneut.
Index: squid/errors/Hungarian/ERR_CANNOT_FORWARD
===================================================================
RCS file: /cvsroot/squid-sf//squid/errors/Hungarian/ERR_CANNOT_FORWARD,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/errors/Hungarian/ERR_CANNOT_FORWARD 26 Jan 2000 03:21:47 -0000 1.1.1.1
+++ squid/errors/Hungarian/ERR_CANNOT_FORWARD 26 Jan 2000 03:23:10 -0000 1.1.1.2
@@ -22,6 +22,6 @@
%F
-%g
Index: squid/errors/German/ERR_READ_TIMEOUT
===================================================================
RCS file: /cvsroot/squid-sf//squid/errors/German/ERR_READ_TIMEOUT,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/errors/German/ERR_READ_TIMEOUT 26 Jan 2000 03:21:47 -0000 1.1.1.1
+++ squid/errors/German/ERR_READ_TIMEOUT 26 Jan 2000 03:23:10 -0000 1.1.1.2
@@ -19,7 +19,7 @@
%E
zurück.
only-if-cached
cache vezérlõ direktíva
található. A dokumentum nincs a cache-ben vagy a dokumentum
-érvényesség-ellenõrzést igényelt volna, ezt azonban a only-if-cached
+érvényesség-ellenõrzést igényelt volna, ezt azonban az only-if-cached
direktíva megtiltotta.
Index: squid/icons/Makefile.in
===================================================================
RCS file: /cvsroot/squid-sf//squid/icons/Attic/Makefile.in,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/icons/Makefile.in 26 Jan 2000 03:21:47 -0000 1.1.1.1
+++ squid/icons/Makefile.in 26 Jan 2000 03:23:10 -0000 1.1.1.2
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+# $Id: Makefile.in,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
#
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -17,7 +17,6 @@
INSTALL_FILE = @INSTALL_DATA@
DEFAULT_ICON_DIR = $(sysconfdir)/icons
-SHARFILE = $(srcdir)/icons.shar
ICONS = anthony-binhex.gif \
anthony-bomb.gif \
anthony-box.gif \
@@ -46,12 +45,9 @@
anthony-xbm.gif \
anthony-xpm.gif
-all: anthony-xpm.gif
+all:
-anthony-xpm.gif: $(SHARFILE)
- $(SH) $(SHARFILE)
-
-$(SHARFILE):
+icons.shar:
shar --no-timestamp $(ICONS) > $@
install: install-mkdirs anthony-xpm.gif
@@ -79,7 +75,7 @@
fi
clean:
- $(RM) -f $(ICONS)
+
distclean: clean
-rm -f Makefile
Index: squid/include/GNUregex.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/include/GNUregex.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/include/GNUregex.h 26 Jan 2000 03:21:47 -0000 1.1.1.1
+++ squid/include/GNUregex.h 26 Jan 2000 03:23:10 -0000 1.1.1.2
@@ -1,5 +1,5 @@
/*
- * $Id: GNUregex.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: GNUregex.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
*/
/* Definitions for data structures and routines for the regular
@@ -389,7 +389,7 @@
* unfortunately clutters up the declarations a bit, but I think it's
* worth it. */
-#ifdef __STDC__
+#if STDC_HEADERS
#define _RE_ARGS(args) args
Index: squid/include/autoconf.h.in
===================================================================
RCS file: /cvsroot/squid-sf//squid/include/Attic/autoconf.h.in,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/include/autoconf.h.in 26 Jan 2000 03:21:47 -0000 1.1.1.1
+++ squid/include/autoconf.h.in 26 Jan 2000 03:23:10 -0000 1.1.1.2
@@ -1,25 +1,4 @@
/* include/autoconf.h.in. Generated automatically from configure.in by autoheader. */
-/*
- * All configurable options are enabled by using --enable-....
- * when running configure. See configure --help for a list
- * of all available options.
- *
- * You are free to edit this file, but it will be overwritten
- * each time you run configure. You may need to edit this file
- * if configure falsely picks up a library function or structure
- * that doesn't really work on your system.
- *
- * Another way to block a function that should not be detected
- * is to
- * setenv ac_cv_func_\n"); dirup = ftpHtmlifyListEntry("", ftpState); @@ -456,7 +492,7 @@ tokens[n_tokens++] = xstrdup(t); xfree(xbuf); /* locate the Month field */ - for (i = 3; i < n_tokens - 3; i++) { + for (i = 3; i < n_tokens - 2; i++) { if (!is_month(tokens[i])) /* Month */ continue; if (!sscanf(tokens[i - 1], SCAN_FTP1, sbuf)) /* Size */ @@ -506,7 +542,23 @@ } snprintf(sbuf, 128, "%s %s", tokens[0], tokens[1]); p->date = xstrdup(sbuf); - p->name = xstrdup(tokens[3]); + if (p->type == 'd') { + /* Directory.. name begins with first printable after */ + ct = strstr(buf, tokens[2]); + ct += strlen(tokens[2]); + while (xisspace(*ct)) + ct++; + if (!*ct) + ct = NULL; + } else { + /* A file. Name begins after size, with a space in between */ + snprintf(sbuf, 128, " %s %s", tokens[2], tokens[3]); + ct = strstr(buf, sbuf); + if (ct) { + ct += strlen(tokens[2]) + 2; + } + } + p->name = xstrdup(ct ? ct : tokens[3]); } /* Try EPLF format; carson@lehman.com */ if (p->name == NULL && buf[0] == '+') { @@ -625,8 +677,8 @@ if ((parts = ftpListParseParts(line, ftpState->flags)) == NULL) { char *p; snprintf(html, 8192, "%s\n", line); - for (p = line; *p && isspace(*p); p++); - if (*p && !isspace(*p)) + for (p = line; *p && xisspace(*p); p++); + if (*p && !xisspace(*p)) ftpState->flags.listformat_unknown = 1; return html; } @@ -770,7 +822,7 @@ xstrncpy(ftpState->data.buf, line, ftpState->data.size); ftpState->data.offset = strlen(ftpState->data.buf); } - memFree(MEM_4K_BUF, line); + memFree(line, MEM_4K_BUF); xfree(sbuf); } @@ -778,12 +830,20 @@ ftpReadComplete(FtpStateData * ftpState) { debug(9, 3) ("ftpReadComplete\n"); + if (ftpState->data.fd > -1) { + /* + * close data socket so it does not occupy resources while + * we wait + */ + comm_close(ftpState->data.fd); + ftpState->data.fd = -1; + } /* Connection closed; retrieval done. */ if (ftpState->flags.html_header_sent) ftpListingFinish(ftpState); if (!ftpState->flags.put) { storeTimestampsSet(ftpState->entry); - storeComplete(ftpState->entry); + fwdComplete(ftpState->fwd); } /* expect the "transfer complete" message on the control socket */ ftpScheduleReadControlReply(ftpState, 1); @@ -803,6 +863,10 @@ delay_id delay_id = delayMostBytesAllowed(mem); #endif assert(fd == ftpState->data.fd); + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { + comm_close(ftpState->ctrl.fd); + return; + } errno = 0; read_sz = ftpState->data.size - ftpState->data.offset; #if DELAY_POOLS @@ -840,7 +904,6 @@ Config.Timeout.read); } else { assert(mem->inmem_hi > 0); - storeAbort(entry, 0); ftpDataTransferDone(ftpState); } } else if (len == 0) { @@ -953,16 +1016,19 @@ } void -ftpStart(request_t * request, StoreEntry * entry, int fd) +ftpStart(FwdState * fwd) { + request_t *request = fwd->request; + StoreEntry *entry = fwd->entry; + int fd = fwd->server_fd; LOCAL_ARRAY(char, realm, 8192); const char *url = storeUrl(entry); FtpStateData *ftpState = xcalloc(1, sizeof(FtpStateData)); HttpReply *reply; StoreEntry *pe = NULL; const cache_key *key = NULL; - cbdataAdd(ftpState, MEM_NONE); - debug(9, 3) ("FtpStart: '%s'\n", url); + cbdataAdd(ftpState, cbdataXfree, 0); + debug(9, 3) ("ftpStart: '%s'\n", url); Counter.server.all.requests++; Counter.server.ftp.requests++; storeLockObject(entry); @@ -971,8 +1037,11 @@ ftpState->ctrl.fd = fd; ftpState->data.fd = -1; ftpState->size = -1; + ftpState->mdtm = -1; ftpState->flags.pasv_supported = 1; ftpState->flags.rest_supported = 1; + ftpState->fwd = fwd; + comm_add_close_handler(fd, ftpStateFree, ftpState); if (ftpState->request->method == METHOD_PUT) ftpState->flags.put = 1; if (!ftpCheckAuth(ftpState, &request->header)) { @@ -993,17 +1062,17 @@ /* create appropriate reply */ ftpAuthRequired(reply, request, realm); httpReplySwapOut(reply, entry); - storeComplete(entry); - ftpStateFree(-1, ftpState); + fwdComplete(ftpState->fwd); + comm_close(fd); return; } ftpCheckUrlpath(ftpState); ftpBuildTitleUrl(ftpState); - debug(9, 5) ("FtpStart: host=%s, path=%s, user=%s, passwd=%s\n", + debug(9, 5) ("ftpStart: host=%s, path=%s, user=%s, passwd=%s\n", ftpState->request->host, strBuf(ftpState->request->urlpath), ftpState->user, ftpState->password); - comm_add_close_handler(fd, ftpStateFree, ftpState); ftpState->state = BEGIN; + ftpState->ctrl.last_command = xstrdup("Connect to server"); ftpState->ctrl.buf = memAllocate(MEM_4K_BUF); ftpState->ctrl.freefunc = memFree4K; ftpState->ctrl.size = 4096; @@ -1054,8 +1123,6 @@ err->request = requestLink(ftpState->request); errorAppendEntry(entry, err); } - if (entry->store_status == STORE_PENDING) - storeAbort(entry, 0); comm_close(ftpState->ctrl.fd); } } @@ -1171,8 +1238,6 @@ err->request = requestLink(ftpState->request); errorAppendEntry(entry, err); } - if (entry->store_status == STORE_PENDING) - storeAbort(entry, 0); comm_close(ftpState->ctrl.fd); } return; @@ -1201,7 +1266,7 @@ ftpHandleControlReply(FtpStateData * ftpState) { char *oldbuf; - wordlist **W, **T; + wordlist **W; int bytes_used = 0; wordlistDestroy(&ftpState->ctrl.message); ftpState->ctrl.message = ftpParseControlReply(ftpState->ctrl.buf, @@ -1228,21 +1293,11 @@ xmemmove(ftpState->ctrl.buf, ftpState->ctrl.buf + bytes_used, ftpState->ctrl.offset); } - /* Extract reply message (last line) */ - for (T = NULL, W = &ftpState->ctrl.message; *W && (*W)->next; W = &(*W)->next) { - /* Skip trailing blank lines */ - if (strlen((*W)->key) == 0) { - if (T == NULL) - T = W; - } else if ((*W)->next) { - T = NULL; - } - } + /* Find the last line of the reply message */ + for (W = &ftpState->ctrl.message; (*W)->next; W = &(*W)->next); safe_free(ftpState->ctrl.last_reply); ftpState->ctrl.last_reply = (*W)->key; safe_free(*W); - if (T) - wordlistDestroy(T); debug(9, 8) ("ftpReadControlReply: state=%d, code=%d\n", ftpState->state, ftpState->ctrl.replycode); FTP_SM_FUNCS[ftpState->state] (ftpState); @@ -1358,6 +1413,8 @@ } if (mode == 'I') ftpState->flags.binary = 1; + else + ftpState->flags.binary = 0; snprintf(cbuf, 1024, "TYPE %c\r\n", mode); ftpWriteCommand(cbuf, ftpState); ftpState->state = SENT_TYPE; @@ -1368,11 +1425,17 @@ { int code = ftpState->ctrl.replycode; char *path; - char *d; + char *d, *p; debug(9, 3) ("This is ftpReadType\n"); if (code == 200) { - path = xstrdup(strBuf(ftpState->request->urlpath)); - for (d = strtok(path, "/"); d; d = strtok(NULL, "/")) { + p = path = xstrdup(strBuf(ftpState->request->urlpath)); + if (*p == '/') + p++; + while (*p) { + d = p; + p += strcspn(p, "/"); + if (*p) + *p++ = '\0'; rfc1738_unescape(d); wordlistAdd(&ftpState->pathcomps, d); } @@ -1425,7 +1488,10 @@ } else { ftpState->flags.no_dotdot = 0; } - snprintf(cbuf, 1024, "CWD %s\r\n", path); + if (*path) + snprintf(cbuf, 1024, "CWD %s\r\n", path); + else + snprintf(cbuf, 1024, "CWD\r\n"); ftpWriteCommand(cbuf, ftpState); ftpState->state = SENT_CWD; } @@ -1549,6 +1615,12 @@ if (code == 213) { ftpUnhack(ftpState); ftpState->size = atoi(ftpState->ctrl.last_reply); + if (ftpState->size == 0) { + debug(9, 2) ("ftpReadSize: SIZE reported %s on %s\n", + ftpState->ctrl.last_reply, + ftpState->title_url); + ftpState->size = -1; + } } else if (code < 0) { ftpFail(ftpState); } @@ -1763,6 +1835,7 @@ /* Fall back on using the same port as the control connection */ debug(9, 3) ("PORT not supported by remote end\n"); comm_close(ftpState->data.fd); + ftpState->data.fd = -1; ftpOpenListenSocket(ftpState, 1); } ftpRestOrList(ftpState); @@ -1789,6 +1862,7 @@ ftpState->data.fd = fd; ftpState->data.port = ntohs(peer.sin_port); ftpState->data.host = xstrdup(inet_ntoa(peer.sin_addr)); + commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout, ftpState); /* XXX We should have a flag to track connect state... @@ -1814,7 +1888,7 @@ ftpState->flags.use_base = 1; } else if (ftpState->flags.isdir) ftpSendList(ftpState); - else if (ftpState->restart_offset > 0) + else if (ftpRestartable(ftpState)) ftpSendRest(ftpState); else ftpSendRetr(ftpState); @@ -1863,6 +1937,24 @@ ftpState->state = SENT_REST; } +static int +ftpRestartable(FtpStateData * ftpState) +{ + if (ftpState->restart_offset > 0) + return 1; + if (!ftpState->request->range) + return 0; + if (!ftpState->flags.binary) + return 0; + if (ftpState->size <= 0) + return 0; + + ftpState->restart_offset = httpHdrRangeLowestOffset(ftpState->request->range, (size_t) ftpState->size); + if (ftpState->restart_offset <= 0) + return 0; + return 1; +} + static void ftpReadRest(FtpStateData * ftpState) { @@ -1870,10 +1962,12 @@ debug(9, 3) ("This is ftpReadRest\n"); assert(ftpState->restart_offset > 0); if (code == 350) { + ftpState->restarted_offset = ftpState->restart_offset; ftpSendRetr(ftpState); } else if (code > 0) { debug(9, 3) ("ftpReadRest: REST not supported\n"); ftpState->flags.rest_supported = 0; + ftpSendRetr(ftpState); } else { ftpFail(ftpState); } @@ -2079,7 +2173,6 @@ ftpState->flags.tried_nlst = 0; /* And off we go */ if (ftpState->flags.isdir) { - safe_free(ftpState->filepath); ftpListDir(ftpState); } else { ftpGetFile(ftpState); @@ -2100,6 +2193,9 @@ static void ftpHackShortcut(FtpStateData * ftpState, FTPSM * nextState) { + /* Clear some unwanted state */ + ftpState->restarted_offset = 0; + ftpState->restart_offset = 0; /* Save old error message & some state info */ if (ftpState->old_request == NULL) { ftpState->old_request = ftpState->ctrl.last_command; @@ -2122,7 +2218,7 @@ if (!ftpState->flags.isdir && /* Not a directory */ !ftpState->flags.try_slash_hack && /* Not in slash hack */ ftpState->mdtm <= 0 && ftpState->size < 0 && /* Not known as a file */ - !strNCaseCmp(ftpState->request->urlpath, "/%2f", 4)) { /* No slash encoded */ + strNCaseCmp(ftpState->request->urlpath, "/%2f", 4) != 0) { /* No slash encoded */ switch (ftpState->state) { case SENT_CWD: case SENT_RETR: @@ -2147,13 +2243,36 @@ break; } } - err = errorCon(ERR_FTP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); + /* Translate FTP errors into HTTP errors */ + err = NULL; + switch (ftpState->state) { + case SENT_USER: + case SENT_PASS: + if (ftpState->ctrl.replycode > 500) + err = errorCon(ERR_FTP_FORBIDDEN, HTTP_FORBIDDEN); + else if (ftpState->ctrl.replycode == 421) + err = errorCon(ERR_FTP_UNAVAILABLE, HTTP_SERVICE_UNAVAILABLE); + break; + case SENT_CWD: + case SENT_RETR: + if (ftpState->ctrl.replycode == 550) + err = errorCon(ERR_FTP_NOT_FOUND, HTTP_NOT_FOUND); + break; + default: + break; + } + if (err == NULL) + err = errorCon(ERR_FTP_FAILURE, HTTP_BAD_GATEWAY); err->request = requestLink(ftpState->request); err->ftp_server_msg = ftpState->ctrl.message; if (ftpState->old_request) err->ftp.request = ftpState->old_request; else err->ftp.request = ftpState->ctrl.last_command; + if (err->ftp.request) { + if (!strncmp(err->ftp.request, "PASS", 4)) + err->ftp.request = "PASS "; + } if (ftpState->old_reply) err->ftp.reply = ftpState->old_reply; else @@ -2162,12 +2281,34 @@ comm_close(ftpState->ctrl.fd); } +void +ftpPumpClosedData(int data_fd, void *data) +{ + FtpStateData *ftpState = data; + assert(data_fd == ftpState->data.fd); + /* + * Ugly pump module closed our server-side. Deal with it. + * The data FD is already closed, so just set it to -1. + */ + ftpState->data.fd = -1; + /* + * Currently, thats all we have to do. Because the upload failed, + * storeAbort() will be called on the reply entry. That will + * call fwdAbort, which closes ftpState->ctrl.fd and then + * ftpStateFree gets called. + */ +} + static void ftpPutStart(FtpStateData * ftpState) { debug(9, 3) ("ftpPutStart\n"); - pumpStart(ftpState->data.fd, ftpState->entry, - ftpState->request, ftpPutTransferDone, ftpState); + /* + * sigh, we need this gross hack to detect when ugly pump module + * aborts and wants to close the server-side. + */ + comm_add_close_handler(ftpState->data.fd, ftpPumpClosedData, ftpState); + pumpStart(ftpState->data.fd, ftpState->fwd, ftpPutTransferDone, ftpState); } static void @@ -2175,6 +2316,7 @@ { FtpStateData *ftpState = data; if (ftpState->data.fd >= 0) { + comm_remove_close_handler(fd, ftpPumpClosedData, ftpState); comm_close(ftpState->data.fd); ftpState->data.fd = -1; } @@ -2229,6 +2371,7 @@ return; ftpState->flags.http_header_sent = 1; assert(e->mem_obj->inmem_hi == 0); + EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT); filename = (t = strRChr(urlpath, '/')) ? t + 1 : strBuf(urlpath); if (ftpState->flags.isdir) { mime_type = "text/html"; @@ -2250,8 +2393,19 @@ storeBuffer(e); httpReplyReset(reply); /* set standard stuff */ - httpReplySetHeaders(reply, 1.0, HTTP_OK, "Gatewaying", - mime_type, ftpState->size, ftpState->mdtm, -2); + if (ftpState->restarted_offset) { + /* Partial reply */ + HttpHdrRangeSpec range_spec; + range_spec.offset = ftpState->restarted_offset; + range_spec.length = ftpState->size - ftpState->restarted_offset; + httpReplySetHeaders(reply, 1.0, HTTP_PARTIAL_CONTENT, "Gatewaying", + mime_type, ftpState->size - ftpState->restarted_offset, ftpState->mdtm, -2); + httpHeaderAddContRange(&reply->header, range_spec, ftpState->size); + } else { + /* Full reply */ + httpReplySetHeaders(reply, 1.0, HTTP_OK, "Gatewaying", + mime_type, ftpState->size, ftpState->mdtm, -2); + } /* additional info */ if (mime_enc) httpHeaderPutStr(&reply->header, HDR_CONTENT_ENCODING, mime_enc); @@ -2268,7 +2422,7 @@ if (pe) storeRelease(pe); storeRelease(e); - } else if (EBIT_TEST(e->flags, ENTRY_CACHABLE)) { + } else if (EBIT_TEST(e->flags, ENTRY_CACHABLE) && !ftpState->restarted_offset) { storeSetPublicKey(e); } else { storeRelease(e); Index: squid/src/globals.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/globals.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/globals.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/globals.h 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: globals.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: globals.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -42,6 +42,7 @@ extern char tmp_error_buf[ERROR_BUF_SZ]; extern char *volatile debug_options; /* NULL */ extern char ThisCache[SQUIDHOSTNAMELEN << 1]; +extern char ThisCache2[SQUIDHOSTNAMELEN << 1]; extern char config_input_line[BUFSIZ]; extern const char *AclMatchedName; /* NULL */ extern const char *DefaultConfigFile; /* DEFAULT_CONFIG_FILE */ @@ -65,13 +66,13 @@ extern fde *fd_table; /* NULL */ extern int Biggest_FD; /* -1 */ extern int Number_FD; /* 0 */ +extern int Opening_FD; /* 0 */ extern int HttpSockets[MAXHTTPPORTS]; extern int NDnsServersAlloc; /* 0 */ extern int NHttpSockets; /* 0 */ extern int RESERVED_FD; extern int Squid_MaxFD; /* SQUID_MAXFD */ extern int config_lineno; /* 0 */ -extern int configured_once; /* 0 */ extern int debugLevels[MAX_DEBUG_SECTIONS]; extern int do_mallinfo; /* 0 */ extern int opt_reuseaddr; /* 1 */ @@ -124,16 +125,17 @@ extern int store_hash_buckets; /* 0 */ extern hash_table *store_table; /* NULL */ extern dlink_list store_list; +extern dlink_list ClientActiveRequests; extern const String StringNull; /* { 0, 0, NULL } */ extern const MemBuf MemBufNull; /* MemBufNULL */ extern int hot_obj_count; /* 0 */ extern int _db_level; extern const int CacheDigestHashFuncCount; /* 4 */ extern CacheDigest *store_digest; /* NULL */ -extern const char *StoreDigestUrlPath; /* "store_digest" */ +extern const char *StoreDigestFileName; /* "store_digest" */ extern const char *StoreDigestMimeStr; /* "application/cache-digest" */ #if USE_CACHE_DIGESTS -extern const Version CacheDigestVer; /* { 4, 3 } */ +extern const Version CacheDigestVer; /* { 5, 3 } */ #endif extern const char *MultipartMsgBoundaryStr; /* "Unique-Squid-Separator" */ extern icpUdpData *IcpQueueHead; /* NULL */ @@ -141,4 +143,4 @@ extern int refresh_nocache_hack; /* 0 */ #endif extern request_flags null_request_flags; -extern int open_disk_fd; /* 0 */ +extern int store_open_disk_fd; /* 0 */ Index: squid/src/gopher.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/gopher.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/gopher.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/gopher.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,7 +1,7 @@ /* - * $Id: gopher.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: gopher.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 10 Gopher * AUTHOR: Harvest Derived @@ -87,6 +87,7 @@ int len; char *buf; /* pts to a 4k page */ int fd; + FwdState *fwdState; } GopherStateData; static PF gopherStateFree; @@ -117,7 +118,7 @@ if (gopherState->entry) { storeUnlockObject(gopherState->entry); } - memFree(MEM_4K_BUF, gopherState->buf); + memFree(gopherState->buf, MEM_4K_BUF); gopherState->buf = NULL; cbdataFree(gopherState); } @@ -186,6 +187,7 @@ break; } memBufPrintf(&mb, "\r\n"); + EBIT_CLR(gopherState->entry->flags, ENTRY_FWD_HDR_WAIT); storeAppend(gopherState->entry, mb.buf, mb.size); memBufClean(&mb); } @@ -573,14 +575,12 @@ { GopherStateData *gopherState = data; StoreEntry *entry = gopherState->entry; - ErrorState *err; debug(10, 4) ("gopherTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); - if (entry->mem_obj->inmem_hi == 0) { - err = errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT); - err->url = xstrdup(gopherState->request); - errorAppendEntry(entry, err); - } else { - storeAbort(entry, 0); + if (entry->store_status == STORE_PENDING) { + if (entry->mem_obj->inmem_hi == 0) { + fwdFail(gopherState->fwdState, + errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT)); + } } comm_close(fd); } @@ -600,6 +600,10 @@ #if DELAY_POOLS delay_id delay_id = delayMostBytesAllowed(entry->mem_obj); #endif + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { + comm_close(fd); + return; + } errno = 0; buf = memAllocate(MEM_4K_BUF); read_sz = 4096 - 1; /* leave room for termination */ @@ -637,7 +641,6 @@ errorAppendEntry(entry, err); comm_close(fd); } else { - storeAbort(entry, 0); comm_close(fd); } } else if (len == 0 && entry->mem_obj->inmem_hi == 0) { @@ -654,7 +657,7 @@ gopherEndHTML(data); storeTimestampsSet(entry); storeBufferFlush(entry); - storeComplete(entry); + fwdComplete(gopherState->fwdState); comm_close(fd); } else { if (gopherState->conversion != NORMAL) { @@ -667,7 +670,7 @@ gopherReadReply, data, 0); } - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); return; } @@ -695,7 +698,7 @@ errorAppendEntry(entry, err); comm_close(fd); if (buf) - memFree(MEM_4K_BUF, buf); /* Allocated by gopherSendRequest. */ + memFree(buf, MEM_4K_BUF); /* Allocated by gopherSendRequest. */ return; } /* @@ -730,7 +733,7 @@ commSetSelect(fd, COMM_SELECT_READ, gopherReadReply, gopherState, 0); commSetDefer(fd, fwdCheckDeferRead, entry); if (buf) - memFree(MEM_4K_BUF, buf); /* Allocated by gopherSendRequest. */ + memFree(buf, MEM_4K_BUF); /* Allocated by gopherSendRequest. */ } /* This will be called when connect completes. Write request. */ @@ -763,8 +766,10 @@ } void -gopherStart(StoreEntry * entry, int fd) +gopherStart(FwdState * fwdState) { + int fd = fwdState->server_fd; + StoreEntry *entry = fwdState->entry; GopherStateData *gopherState = CreateGopherStateData(); storeLockObject(entry); gopherState->entry = entry; @@ -797,11 +802,12 @@ } } gopherToHTML(gopherState, (char *) NULL, 0); - storeComplete(entry); + fwdComplete(fwdState); comm_close(fd); return; } gopherState->fd = fd; + gopherState->fwdState = fwdState; commSetSelect(fd, COMM_SELECT_WRITE, gopherSendRequest, gopherState, 0); commSetTimeout(fd, Config.Timeout.read, gopherTimeout, gopherState); } @@ -810,7 +816,7 @@ CreateGopherStateData(void) { GopherStateData *gd = xcalloc(1, sizeof(GopherStateData)); - cbdataAdd(gd, MEM_NONE); + cbdataAdd(gd, cbdataXfree, 0); gd->buf = memAllocate(MEM_4K_BUF); return (gd); } Index: squid/src/helper.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/helper.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/helper.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/helper.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -59,7 +59,7 @@ } hlp->n_running++; srv = memAllocate(MEM_HELPER_SERVER); - cbdataAdd(srv, MEM_HELPER_SERVER); + cbdataAdd(srv, memFree, MEM_HELPER_SERVER); srv->flags.alive = 1; srv->index = k; srv->rfd = rfd; @@ -114,6 +114,7 @@ { helper_server *srv; dlink_node *link; + double tt; storeAppendPrintf(sentry, "number running: %d of %d\n", hlp->n_running, hlp->n_to_start); storeAppendPrintf(sentry, "requests sent: %d\n", @@ -134,6 +135,7 @@ "Offset"); for (link = hlp->servers.head; link; link = link->next) { srv = link->data; + tt = 0.001 * tvSubMsec(srv->dispatch_time, current_time); storeAppendPrintf(sentry, "%7d\t%7d\t%11d\t%c%c%c%c\t%7.3f\t%7d\n", srv->index + 1, srv->rfd, @@ -142,7 +144,7 @@ srv->flags.busy ? 'B' : ' ', srv->flags.closing ? 'C' : ' ', srv->flags.shutdown ? 'S' : ' ', - 0.001 * tvSubMsec(srv->dispatch_time, current_time), + tt < 0.0 ? 0.0 : tt, (int) srv->offset); } storeAppendPrintf(sentry, "\nFlags key:\n\n"); @@ -177,7 +179,7 @@ continue; } srv->flags.closing = 1; - comm_close(srv->wfd); + comm_close(srv->rfd); } } @@ -185,7 +187,7 @@ helperCreate(const char *name) { helper *hlp = memAllocate(MEM_HELPER); - cbdataAdd(hlp, MEM_HELPER); + cbdataAdd(hlp, memFree, MEM_HELPER); hlp->id_name = name; return hlp; } @@ -209,11 +211,18 @@ { helper_server *srv = data; helper *hlp = srv->parent; + helper_request *r; assert(srv->rfd == fd); if (srv->buf) { - memFree(MEM_8K_BUF, srv->buf); + memFree(srv->buf, MEM_8K_BUF); srv->buf = NULL; } + if ((r = srv->request)) { + if (cbdataValid(r->data)) + r->callback(r->data, srv->buf); + helperRequestFree(r); + srv->request = NULL; + } if (srv->wfd != srv->rfd) comm_close(srv->wfd); dlinkDelete(&srv->link, &hlp->servers); @@ -268,6 +277,7 @@ srv->flags.busy = 0; srv->offset = 0; helperRequestFree(r); + srv->request = NULL; hlp->stats.replies++; hlp->stats.avg_svc_time = intAverage(hlp->stats.avg_svc_time, @@ -310,7 +320,7 @@ if ((link = hlp->queue.head)) { r = link->data; dlinkDelete(link, &hlp->queue); - memFree(MEM_DLINK_NODE, link); + memFree(link, MEM_DLINK_NODE); hlp->stats.queue_size--; } return r; @@ -377,5 +387,5 @@ { cbdataUnlock(r->data); xfree(r->buf); - memFree(MEM_HELPER_REQUEST, r); + memFree(r, MEM_HELPER_REQUEST); } Index: squid/src/http.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/http.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/http.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/http.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: http.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: http.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -42,12 +42,12 @@ static const char *const crlf = "\r\n"; -static CNCB httpConnectDone; static CWCB httpSendComplete; static CWCB httpSendRequestEntry; +static CWCB httpSendRequestEntryDone; static PF httpReadReply; -static PF httpSendRequest; +static void httpSendRequest(HttpStateData *); static PF httpStateFree; static PF httpTimeout; static void httpCacheNegatively(StoreEntry *); @@ -57,14 +57,17 @@ static void httpMaybeRemovePublic(StoreEntry *, http_status); static void -httpStateFree(int fdnotused, void *data) +httpStateFree(int fd, void *data) { HttpStateData *httpState = data; +#if DELAY_POOLS + delayClearNoDelay(fd); +#endif if (httpState == NULL) return; storeUnlockObject(httpState->entry); if (httpState->reply_hdr) { - memFree(MEM_8K_BUF, httpState->reply_hdr); + memFree(httpState->reply_hdr, MEM_8K_BUF); httpState->reply_hdr = NULL; } requestUnlink(httpState->request); @@ -90,11 +93,11 @@ HttpStateData *httpState = data; StoreEntry *entry = httpState->entry; debug(11, 4) ("httpTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); - assert(entry->store_status == STORE_PENDING); - if (entry->mem_obj->inmem_hi == 0) { - fwdFail(httpState->fwdState, ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT, 0); - } else { - storeAbort(entry, 0); + if (entry->store_status == STORE_PENDING) { + if (entry->mem_obj->inmem_hi == 0) { + fwdFail(httpState->fwd, + errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT)); + } } comm_close(fd); } @@ -221,6 +224,12 @@ case HTTP_MULTIPLE_CHOICES: case HTTP_MOVED_PERMANENTLY: case HTTP_GONE: + /* + * Don't cache objects that need to be refreshed on next request, + * unless we know how to refresh it. + */ + if (!refreshIsCachable(httpState->entry)) + return 0; /* don't cache objects from peers w/o LMT, Date, or Expires */ /* check that is it enough to check headers @?@ */ if (rep->date > -1) @@ -375,6 +384,15 @@ /* * What does the reply have to say about keep-alive? */ + /* + * XXX BUG? + * If the origin server (HTTP/1.0) does not send a keep-alive + * header, but keeps the connection open anyway, what happens? + * We'll return here and http.c waits for an EOF before changing + * store_status to STORE_OK. Combine this with ENTRY_FWD_HDR_WAIT + * and an error status code, and we might have to wait until + * the server times out the socket. + */ if (!reply->keep_alive) return 0; debug(11, 5) ("httpPconnTransferDone: content_length=%d\n", @@ -430,8 +448,18 @@ int clen; size_t read_sz; #if DELAY_POOLS - delay_id delay_id = delayMostBytesAllowed(entry->mem_obj); + delay_id delay_id; + + /* special "if" only for http (for nodelay proxy conns) */ + if (delayIsNoDelay(fd)) + delay_id = 0; + else + delay_id = delayMostBytesAllowed(entry->mem_obj); #endif + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { + comm_close(fd); + return; + } /* check if we want to defer reading */ errno = 0; read_sz = SQUID_TCP_SO_RCVBUF; @@ -456,7 +484,7 @@ } if (!httpState->reply_hdr && len > 0) { /* Skip whitespace */ - while (len > 0 && isspace(*buf)) + while (len > 0 && xisspace(*buf)) xmemmove(buf, buf + 1, len--); if (len == 0) { /* Continue to read... */ @@ -470,14 +498,19 @@ if (ignoreErrno(errno)) { commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0); } else if (entry->mem_obj->inmem_hi == 0) { - fwdFail(httpState->fwdState, ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, errno); + ErrorState *err; + err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR); + err->xerrno = errno; + fwdFail(httpState->fwd, err); comm_close(fd); } else { - storeAbort(entry, 0); comm_close(fd); } } else if (len == 0 && entry->mem_obj->inmem_hi == 0) { - fwdFail(httpState->fwdState, ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE, errno); + ErrorState *err; + err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE); + err->xerrno = errno; + fwdFail(httpState->fwd, err); httpState->eof = 1; comm_close(fd); } else if (len == 0) { @@ -491,47 +524,43 @@ * we want to process the reply headers. */ httpProcessReplyHeader(httpState, buf, len); -#ifdef PPNR_WIP - storePPNR(entry); -#endif /* PPNR_WIP */ - storeComplete(entry); /* deallocates mem_obj->request */ + fwdComplete(httpState->fwd); comm_close(fd); } else { -#ifndef PPNR_WIP - if (httpState->reply_hdr_state < 2) -#else if (httpState->reply_hdr_state < 2) { -#endif /* PPNR_WIP */ httpProcessReplyHeader(httpState, buf, len); -#ifdef PPNR_WIP - if (httpState->reply_hdr_state == 2) - storePPNR(entry); + if (httpState->reply_hdr_state == 2) { + http_status s = entry->mem_obj->reply->sline.status; + /* + * If its not a reply that we will re-forward, then + * allow the client to get it. + */ + if (!fwdReforwardableStatus(s)) + EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + } } -#endif /* PPNR_WIP */ storeAppend(entry, buf, len); -#ifdef OPTIMISTIC_IO - if (entry->store_status == STORE_ABORTED) { + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { /* * the above storeAppend() call could ABORT this entry, * in that case, the server FD should already be closed. * there's nothing for us to do. */ (void) 0; - } else -#endif - if (httpPconnTransferDone(httpState)) { + } else if (httpPconnTransferDone(httpState)) { /* yes we have to clear all these! */ commSetDefer(fd, NULL, NULL); commSetTimeout(fd, -1, NULL, NULL); commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); +#if DELAY_POOLS + delayClearNoDelay(fd); +#endif comm_remove_close_handler(fd, httpStateFree, httpState); - storeComplete(entry); /* deallocates mem_obj->request */ - /* call storeComplete BEFORE fwdUnregister or else fwdUnregister - * will storeAbort */ - fwdUnregister(fd, httpState->fwdState); + fwdUnregister(fd, httpState->fwd); pconnPush(fd, request->host, request->port); + fwdComplete(httpState->fwd); httpState->fd = -1; - httpStateFree(-1, httpState); + httpStateFree(fd, httpState); } else { /* Wait for EOF condition */ commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0); @@ -565,10 +594,16 @@ return; } else { /* Schedule read reply. */ - commSetSelect(fd, - COMM_SELECT_READ, - httpReadReply, - httpState, 0); + commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0); + /* + * Set the read timeout here because it hasn't been set yet. + * We only set the read timeout after the request has been + * fully written to the server-side. If we start the timeout + * after connection establishment, then we are likely to hit + * the timeout for POST/PUT requests that have very large + * request bodies. + */ + commSetTimeout(fd, Config.Timeout.read, httpTimeout, httpState); commSetDefer(fd, fwdCheckDeferRead, entry); } } @@ -605,7 +640,7 @@ * - we can actually parse client Range specs * - the specs are expected to be simple enough (e.g. no out-of-order ranges) * - reply will be cachable - * (If the reply will be uncachable we have to though it away after + * (If the reply will be uncachable we have to throw it away after * serving this request, so it is better to forward ranges to * the server and fetch only the requested content) */ @@ -726,6 +761,8 @@ if (strLen(request->urlpath)) assert(strstr(url, strBuf(request->urlpath))); } + if (flags.only_if_cached) + EBIT_SET(cc->mask, CC_ONLY_IF_CACHED); httpHeaderPutCc(hdr_out, cc); httpHdrCcDestroy(cc); } @@ -768,12 +805,10 @@ memBufAppend(mb, crlf, 2); return mb->size - offset; } - /* This will be called when connect completes. Write request. */ static void -httpSendRequest(int fd, void *data) +httpSendRequest(HttpStateData * httpState) { - HttpStateData *httpState = data; MemBuf mb; request_t *req = httpState->request; StoreEntry *entry = httpState->entry; @@ -781,7 +816,7 @@ peer *p = httpState->peer; CWCB *sendHeaderDone; - debug(11, 5) ("httpSendRequest: FD %d: httpState %p.\n", fd, httpState); + debug(11, 5) ("httpSendRequest: FD %d: httpState %p.\n", httpState->fd, httpState); if (pumpMethod(req->method)) sendHeaderDone = httpSendRequestEntry; @@ -806,6 +841,9 @@ httpState->flags.keepalive = 1; else if ((double) p->stats.n_keepalives_recv / (double) p->stats.n_keepalives_sent > 0.50) httpState->flags.keepalive = 1; + if (httpState->peer) + if (neighborType(httpState->peer, httpState->request) == PEER_SIBLING) + httpState->flags.only_if_cached = 1; memBufDefInit(&mb); httpBuildRequestPrefix(req, httpState->orig_request, @@ -813,26 +851,27 @@ &mb, cfd, httpState->flags); - debug(11, 6) ("httpSendRequest: FD %d:\n%s\n", fd, mb.buf); - comm_write_mbuf(fd, mb, sendHeaderDone, httpState); + debug(11, 6) ("httpSendRequest: FD %d:\n%s\n", httpState->fd, mb.buf); + comm_write_mbuf(httpState->fd, mb, sendHeaderDone, httpState); } void -httpStart(FwdState * fwdState, int fd) +httpStart(FwdState * fwd) { + int fd = fwd->server_fd; HttpStateData *httpState = memAllocate(MEM_HTTP_STATE_DATA); request_t *proxy_req; - request_t *orig_req = fwdState->request; + request_t *orig_req = fwd->request; debug(11, 3) ("httpStart: \"%s %s\"\n", RequestMethodStr[orig_req->method], - storeUrl(fwdState->entry)); - cbdataAdd(httpState, MEM_HTTP_STATE_DATA); - storeLockObject(fwdState->entry); - httpState->fwdState = fwdState; - httpState->entry = fwdState->entry; + storeUrl(fwd->entry)); + cbdataAdd(httpState, memFree, MEM_HTTP_STATE_DATA); + storeLockObject(fwd->entry); + httpState->fwd = fwd; + httpState->entry = fwd->entry; httpState->fd = fd; - if (fwdState->servers) - httpState->peer = fwdState->servers->peer; /* might be NULL */ + if (fwd->servers) + httpState->peer = fwd->servers->peer; /* might be NULL */ if (httpState->peer) { proxy_req = requestCreate(orig_req->method, PROTO_NONE, storeUrl(httpState->entry)); @@ -851,11 +890,9 @@ if (httpState->peer->options.proxy_only) storeReleaseRequest(httpState->entry); #if DELAY_POOLS - if (httpState->peer->options.no_delay) { - proxy_req->delay_id = 0; - } else { - proxy_req->delay_id = orig_req->delay_id; - } + assert(delayIsNoDelay(fd) == 0); + if (httpState->peer->options.no_delay) + delaySetNoDelay(fd); #endif } else { httpState->request = requestLink(orig_req); @@ -867,46 +904,52 @@ comm_add_close_handler(fd, httpStateFree, httpState); Counter.server.all.requests++; Counter.server.http.requests++; - httpConnectDone(fd, COMM_OK, httpState); + httpSendRequest(httpState); + /* + * We used to set the read timeout here, but not any more. + * Now its set in httpSendComplete() after the full request, + * including request body, has been written to the server. + */ } static void -httpConnectDone(int fd, int status, void *data) +httpSendRequestEntry(int fd, char *bufnotused, size_t size, int errflag, void *data) { HttpStateData *httpState = data; - request_t *request = httpState->request; StoreEntry *entry = httpState->entry; ErrorState *err; - if (status == COMM_ERR_DNS) { - debug(11, 4) ("httpConnectDone: Unknown host: %s\n", request->host); - err = errorCon(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE); - err->dnsserver_msg = xstrdup(dns_error_message); - err->request = requestLink(httpState->orig_request); - errorAppendEntry(entry, err); - comm_close(fd); - } else if (status != COMM_OK) { - err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); + debug(11, 5) ("httpSendRequestEntry: FD %d: size %d: errflag %d.\n", + fd, size, errflag); + if (size > 0) { + fd_bytes(fd, size, FD_WRITE); + kb_incr(&Counter.server.all.kbytes_out, size); + kb_incr(&Counter.server.http.kbytes_out, size); + } + if (errflag == COMM_ERR_CLOSING) + return; + if (errflag) { + err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; - err->host = xstrdup(request->host); - err->port = request->port; err->request = requestLink(httpState->orig_request); errorAppendEntry(entry, err); - if (httpState->peer) - peerCheckConnectStart(httpState->peer); comm_close(fd); - } else { - commSetSelect(fd, COMM_SELECT_WRITE, httpSendRequest, httpState, 0); - commSetTimeout(fd, Config.Timeout.read, httpTimeout, httpState); + return; } + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { + comm_close(fd); + return; + } + pumpStart(fd, httpState->fwd, httpSendRequestEntryDone, httpState); } static void -httpSendRequestEntry(int fd, char *bufnotused, size_t size, int errflag, void *data) +httpSendRequestEntryDone(int fd, char *bufnotused, size_t size, int errflag, void *data) { HttpStateData *httpState = data; StoreEntry *entry = httpState->entry; ErrorState *err; - debug(11, 5) ("httpSendRequestEntry: FD %d: size %d: errflag %d.\n", + aclCheck_t ch; + debug(11, 5) ("httpSendRequestEntryDone: FD %d: size %d: errflag %d.\n", fd, size, errflag); if (size > 0) { fd_bytes(fd, size, FD_WRITE); @@ -923,5 +966,16 @@ comm_close(fd); return; } - pumpStart(fd, entry, httpState->orig_request, httpSendComplete, httpState); + memset(&ch, '\0', sizeof(ch)); + ch.request = httpState->request; + if (!Config.accessList.brokenPosts) { + debug(11, 5) ("httpSendRequestEntryDone: No brokenPosts list\n"); + httpSendComplete(fd, NULL, 0, 0, data); + } else if (!aclCheckFast(Config.accessList.brokenPosts, &ch)) { + debug(11, 5) ("httpSendRequestEntryDone: didn't match brokenPosts\n"); + httpSendComplete(fd, NULL, 0, 0, data); + } else { + debug(11, 2) ("httpSendRequestEntryDone: matched brokenPosts\n"); + comm_write(fd, "\r\n", 2, httpSendComplete, data, NULL); + } } Index: squid/src/icmp.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/icmp.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/icmp.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/icmp.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: icmp.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: icmp.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 37 ICMP Routines * AUTHOR: Duane Wessels @@ -169,7 +169,7 @@ strcpy(payload + len, url); len += ulen + 1; icmpSendEcho(to, S_ICMP_ICP, payload, len); - memFree(MEM_8K_BUF, payload); + memFree(payload, MEM_8K_BUF); #endif } #endif Index: squid/src/icp_v2.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/icp_v2.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/icp_v2.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/icp_v2.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: icp_v2.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: icp_v2.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 12 Internet Cache Protocol * AUTHOR: Duane Wessels @@ -218,6 +218,7 @@ break; } checklist.src_addr = from.sin_addr; + checklist.my_addr = no_addr; checklist.request = icp_request; allow = aclCheckFast(Config.accessList.icp, &checklist); if (!allow) { @@ -271,7 +272,9 @@ break; case ICP_HIT: +#if ALLOW_SOURCE_PING case ICP_SECHO: +#endif case ICP_DECHO: case ICP_MISS: case ICP_DENIED: @@ -492,6 +495,7 @@ if (theOutIcpConnection > -1) { debug(12, 1) ("FD %d Closing ICP connection\n", theOutIcpConnection); comm_close(theOutIcpConnection); + theOutIcpConnection = -1; } } Index: squid/src/icp_v3.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/icp_v3.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/icp_v3.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/icp_v3.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: icp_v3.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: icp_v3.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 12 Internet Cache Protocol * AUTHOR: Duane Wessels @@ -72,6 +72,7 @@ break; } checklist.src_addr = from.sin_addr; + checklist.my_addr = no_addr; checklist.request = icp_request; allow = aclCheckFast(Config.accessList.icp, &checklist); if (!allow) { @@ -112,7 +113,9 @@ break; case ICP_HIT: +#if ALLOW_SOURCE_PING case ICP_SECHO: +#endif case ICP_DECHO: case ICP_MISS: case ICP_DENIED: Index: squid/src/ident.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/ident.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/ident.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/ident.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: ident.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: ident.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 30 Ident (RFC 931) * AUTHOR: Duane Wessels @@ -35,113 +35,210 @@ #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 { + char *key; + struct _IdentStateData *next; + int fd; /* IDENT fd */ + struct sockaddr_in me; + struct sockaddr_in peer; + IdentClient *clients; +} IdentStateData; static PF identReadReply; static PF identClose; static PF identTimeout; static CNCB identConnectDone; -static void identCallback(ConnStateData * connState); +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)) { + state->clients = client->next; + if (cbdataValid(client->callback_data)) + client->callback(result, client->callback_data); + cbdataUnlock(client->callback_data); + xfree(client); + } +} static void identClose(int fdnotused, void *data) { - ConnStateData *connState = data; - connState->ident.fd = -1; + 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) { - ConnStateData *connState = data; + IdentStateData *state = data; debug(30, 3) ("identTimeout: FD %d, %s\n", fd, - inet_ntoa(connState->peer.sin_addr)); + inet_ntoa(state->peer.sin_addr)); comm_close(fd); } -/* start a TCP connection to the peer host on port 113 */ -void -identStart(int fd, ConnStateData * connState, IDCB * callback, void *data) -{ - connState->ident.callback = callback; - connState->ident.callback_data = data; - connState->ident.state = IDENT_PENDING; - if (fd < 0) { - fd = comm_open(SOCK_STREAM, - 0, - connState->me.sin_addr, - 0, - COMM_NONBLOCKING, - "ident"); - if (fd == COMM_ERROR) { - identCallback(connState); - return; - } - } - connState->ident.fd = fd; - comm_add_close_handler(fd, - identClose, - connState); - commConnectStart(fd, - inet_ntoa(connState->peer.sin_addr), - IDENT_PORT, - identConnectDone, - connState); -} - static void identConnectDone(int fd, int status, void *data) { - ConnStateData *connState = data; + IdentStateData *state = data; + IdentClient *c; MemBuf mb; if (status != COMM_OK) { + /* Failed to connect */ + comm_close(fd); + return; + } + /* + * see if our clients still care + */ + for (c = state->clients; c; c = c->next) { + if (cbdataValid(c->callback_data)) + break; + } + if (c == NULL) { + /* no clients care */ comm_close(fd); - identCallback(connState); return; } memBufDefInit(&mb); memBufPrintf(&mb, "%d, %d\r\n", - ntohs(connState->peer.sin_port), - ntohs(connState->me.sin_port)); - comm_write_mbuf(fd, mb, NULL, connState); - commSetSelect(fd, COMM_SELECT_READ, identReadReply, connState, 0); - commSetTimeout(fd, Config.Timeout.read, identTimeout, connState); + ntohs(state->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) { - ConnStateData *connState = data; + IdentStateData *state = data; LOCAL_ARRAY(char, buf, BUFSIZ); + char *ident = NULL; char *t = NULL; int len = -1; - buf[0] = '\0'; Counter.syscalls.sock.reads++; len = read(fd, buf, BUFSIZ - 1); fd_bytes(fd, len, FD_READ); - if (len > 0) { - 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 ((t = strrchr(buf, ':'))) { - while (isspace(*++t)); - xstrncpy(connState->ident.ident, t, USER_IDENT_SZ); - } + 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); - identCallback(connState); } + static void -identCallback(ConnStateData * connState) +identClientAdd(IdentStateData * state, IDCB * callback, void *callback_data) +{ + IdentClient *c = xcalloc(1, sizeof(*c)); + IdentClient **C; + c->callback = callback; + c->callback_data = callback_data; + cbdataLock(callback_data); + for (C = &state->clients; *C; C = &(*C)->next); + *C = c; +} + +/**** PUBLIC FUNCTIONS ****/ + +/* + * start a TCP connection to the peer host on port 113 + */ +void +identStart(struct sockaddr_in *me, struct sockaddr_in *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(peer->sin_addr), + ntohs(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; + } + state = xcalloc(1, sizeof(IdentStateData)); + cbdataAdd(state, cbdataXfree, 0); + state->key = xstrdup(key); + state->fd = fd; + state->me = *me; + state->peer = *peer; + identClientAdd(state, callback, data); + hash_join(ident_hash, (hash_link *) state); + comm_add_close_handler(fd, + identClose, + state); + commSetTimeout(fd, Config.Timeout.ident, identTimeout, state); + commConnectStart(fd, + inet_ntoa(state->peer.sin_addr), + IDENT_PORT, + identConnectDone, + state); +} + +void +identInit(void) { - connState->ident.state = IDENT_DONE; - if (connState->ident.callback) - connState->ident.callback(connState->ident.callback_data); + ident_hash = hash_create((HASHCMP *) strcmp, + hashPrime(Squid_MaxFD / 8), + hash4); } + +#endif Index: squid/src/internal.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/internal.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/internal.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/internal.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: internal.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: internal.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 76 Internal Squid Object handling * AUTHOR: Duane, Alex, Henrik Index: squid/src/ipc.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/ipc.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/ipc.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/ipc.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: ipc.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: ipc.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 54 Interprocess Communication * AUTHOR: Duane Wessels @@ -66,6 +66,7 @@ int cwfd = -1; int pwfd = -1; int fd; + int t1, t2, t3; socklen_t len; int tmp_s; #if HAVE_PUTENV @@ -207,9 +208,9 @@ /* child */ no_suid(); /* give up extra priviliges */ /* close shared socket with parent */ - comm_close(prfd); + close(prfd); if (pwfd != prfd) - comm_close(pwfd); + close(pwfd); pwfd = prfd = -1; if (type == IPC_TCP_SOCKET) { @@ -218,7 +219,7 @@ debug(50, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror()); _exit(1); } - debug(54, 3) ("ipcCreate: accepted new FD %d\n", fd); + debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd); close(crfd); cwfd = crfd = fd; } else if (type == IPC_UDP_SOCKET) { @@ -244,20 +245,27 @@ snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions); putenv(env_str); #endif - dup2(crfd, 0); - dup2(cwfd, 1); - dup2(fileno(debug_log), 2); - fclose(debug_log); /* - * Solaris pthreads seems to close FD 0 upon fork(), so don't close - * this FD if its 0, 1, or 2. - * -- Michael O'Reilly + * This double-dup stuff avoids problems when one of + * crfd, cwfd, or debug_log are in the rage 0-2. */ - if (crfd > 2) - close(crfd); - if (cwfd != crfd) - if (cwfd > 2) - close(cwfd); + do { + x = open(_PATH_DEVNULL, 0, 0444); + commSetCloseOnExec(x); + } while (x < 3); + t1 = dup(crfd); + t2 = dup(cwfd); + t3 = dup(fileno(debug_log)); + assert(t1 > 2 && t2 > 2 && t3 > 2); + close(crfd); + close(cwfd); + close(fileno(debug_log)); + dup2(t1, 0); + dup2(t2, 1); + dup2(t3, 2); + close(t1); + close(t2); + close(t3); #if HAVE_SETSID setsid(); #endif Index: squid/src/ipcache.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/ipcache.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/ipcache.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/ipcache.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: ipcache.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: ipcache.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 14 IP Cache * AUTHOR: Harvest Derived @@ -126,7 +126,7 @@ } safe_free(i->name); safe_free(i->error_message); - memFree(MEM_IPCACHE_ENTRY, i); + memFree(i, MEM_IPCACHE_ENTRY); return; } @@ -175,7 +175,7 @@ ipcache_release(i); removed++; } - debug(14, 3) ("ipcache_purgelru: removed %d entries\n", removed); + debug(14, 9) ("ipcache_purgelru: removed %d entries\n", removed); } /* create blank ipcache_entry */ @@ -247,7 +247,7 @@ } cbdataUnlock(p->handlerData); } - memFree(MEM_IPCACHE_PENDING, p); + memFree(p, MEM_IPCACHE_PENDING); } i->pending_head = NULL; /* nuke list */ debug(14, 10) ("ipcache_call_pending: Called %d handlers.\n", nhandler); @@ -270,10 +270,11 @@ i.status = IP_NEGATIVE_CACHED; if (inbuf == NULL) { debug(14, 1) ("ipcacheParse: Got reply\n"); + i.error_message = xstrdup("Internal Squid Error"); return &i; } xstrncpy(buf, inbuf, DNS_INBUF_SZ); - debug(14, 5) ("ipcacheParse: parsing:%s\n", buf); + debug(14, 5) ("ipcacheParse: parsing: {%s}\n", buf); token = strtok(buf, w_space); if (NULL == token) { debug(14, 1) ("ipcacheParse: Got , expecting '$addr'\n"); @@ -416,7 +417,7 @@ /* for HIT, PENDING, DISPATCHED we've returned. For MISS we submit */ c = xcalloc(1, sizeof(*c)); c->data = i; - cbdataAdd(c, MEM_NONE); + cbdataAdd(c, cbdataXfree, 0); i->status = IP_DISPATCHED; ipcacheLockEntry(i); dnsSubmit(i->name, ipcacheHandleReply, c); @@ -722,13 +723,13 @@ ip_pending *p; while ((p = i->pending_head)) { i->pending_head = p->next; - memFree(MEM_IPCACHE_PENDING, p); + memFree(p, MEM_IPCACHE_PENDING); } safe_free(i->addrs.in_addrs); safe_free(i->addrs.bad_mask); safe_free(i->name); safe_free(i->error_message); - memFree(MEM_IPCACHE_ENTRY, i); + memFree(i, MEM_IPCACHE_ENTRY); } void @@ -825,12 +826,6 @@ case IP_LOC: *(Answer->val.integer) = IpcacheStats.release_locked; break; -#if DELETE_ME - case IP_LENG: - *(Answer->val.integer) = queue_length; - Answer->type = SMI_GAUGE32; - break; -#endif default: *ErrP = SNMP_ERR_NOSUCHNAME; snmp_var_free(Answer); Index: squid/src/leakfinder.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/leakfinder.c,v retrieving revision 1.1 retrieving revision 1.1.1.1 diff -u -r1.1 -r1.1.1.1 --- squid/src/leakfinder.c 26 Jan 2000 03:23:10 -0000 1.1 +++ squid/src/leakfinder.c 26 Jan 2000 03:23:10 -0000 1.1.1.1 @@ -1,6 +1,6 @@ /* - * $Id: leakfinder.c,v 1.1 2000/01/26 03:23:10 hno Exp $ + * $Id: leakfinder.c,v 1.1.1.1 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 45 Callback Data Registry * AUTHOR: Duane Wessels Index: squid/src/main.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/main.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/main.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/main.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: main.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: main.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 1 Startup and Main Loop * AUTHOR: Harvest Derived @@ -40,8 +40,10 @@ static int opt_send_signal = -1; static int opt_no_daemon = 0; +static int opt_parse_cfg_only = 0; static int httpPortNumOverride = 1; static int icpPortNumOverride = 1; /* Want to detect "-u 0" */ +static int configured_once = 0; #if MALLOC_DBG static int malloc_debug_level = 0; #endif @@ -68,6 +70,7 @@ extern void log_trace_init(char *); #endif static EVH SquidShutdown; +static void mainSetCwd(void); static void usage(void) @@ -79,8 +82,9 @@ " -f file Use given config-file instead of\n" " %s\n" " -h Print help message.\n" - " -k reconfigure|rotate|shutdown|interrupt|kill|debug|check\n" - " Send signal to running copy and exit.\n" + " -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parse\n" + " Parse configuration file, then send signal to \n" + " running copy (except -k parse) and exit.\n" " -s Enable logging to syslog.\n" " -u port Specify ICP port number (default: %d), disable with 0.\n" " -v Print version.\n" @@ -152,13 +156,13 @@ if (!strncmp(optarg, "reconfigure", strlen(optarg))) opt_send_signal = SIGHUP; else if (!strncmp(optarg, "rotate", strlen(optarg))) -#if (defined(_SQUID_LINUX_) && USE_ASYNC_IO) +#ifdef _SQUID_LINUX_THREADS_ opt_send_signal = SIGQUIT; #else opt_send_signal = SIGUSR1; #endif else if (!strncmp(optarg, "debug", strlen(optarg))) -#if (defined(_SQUID_LINUX_) && USE_ASYNC_IO) +#ifdef _SQUID_LINUX_THREADS_ opt_send_signal = SIGTRAP; #else opt_send_signal = SIGUSR2; @@ -171,6 +175,8 @@ opt_send_signal = SIGKILL; else if (!strncmp(optarg, "check", strlen(optarg))) opt_send_signal = 0; /* SIGNULL */ + else if (!strncmp(optarg, "parse", strlen(optarg))) + opt_parse_cfg_only = 1; /* parse cfg file only */ else usage(); break; @@ -335,6 +341,7 @@ debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n"); } storeDirOpenSwapLogs(); + writePidFile(); /* write PID file */ debug(1, 1) ("Ready to serve requests.\n"); reconfiguring = 0; } @@ -355,6 +362,9 @@ setEffectiveUser(void) { leave_suid(); /* Run as non privilegied user */ +#ifdef _SQUID_OS2_ + return; +#endif if (geteuid() == 0) { debug(0, 0) ("Squid is not safe to run as root! If you must\n"); debug(0, 0) ("start Squid as root, then you must configure\n"); @@ -365,6 +375,34 @@ } static void +mainSetCwd(void) +{ + if (Config.coredump_dir) { + if (!chdir(Config.coredump_dir)) { + debug(0, 1) ("Set Current Directory to %s\n", Config.coredump_dir); + return; + } else { + debug(50, 0) ("chdir: %s: %s\n", Config.coredump_dir, xstrerror()); + } + } + if (!Config.effectiveUser) { + char *p = getcwd(NULL, 0); + debug(0, 1) ("Current Directory is %s\n", p); + xfree(p); + return; + } + /* we were probably started as root, so cd to a swap + * directory in case we dump core */ + if (!chdir(storeSwapDir(0))) { + debug(0, 1) ("Set Current Directory to %s\n", storeSwapDir(0)); + return; + } else { + debug(50, 0) ("%s: %s\n", storeSwapDir(0), xstrerror()); + fatal_dump("Cannot cd to swap directory?"); + } +} + +static void mainInitialize(void) { if (opt_catch_signals) { @@ -374,14 +412,6 @@ squid_signal(SIGPIPE, SIG_IGN, SA_RESTART); squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART); - if (!configured_once) { - cbdataInit(); - memInit(); /* memInit must go before config parsing */ - } - if (ConfigFile == NULL) - ConfigFile = xstrdup(DefaultConfigFile); - parseConfigFile(ConfigFile); - setEffectiveUser(); assert(Config.Port.http); if (httpPortNumOverride != 1) @@ -409,10 +439,12 @@ authenticateInit(); useragentOpenLog(); httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */ - httpAnonInitModule(); /* must go before accepting requests */ httpReplyInitModule(); /* must go before accepting replies */ errorInitialize(); accessLogInit(); +#if USE_IDENT + identInit(); +#endif #ifdef SQUID_SNMP snmpInit(); #endif @@ -427,14 +459,7 @@ cachemgrInit(); statInit(); storeInit(); - if (Config.effectiveUser) { - /* we were probably started as root, so cd to a swap - * directory in case we dump core */ - if (chdir(storeSwapDir(0)) < 0) { - debug(50, 0) ("%s: %s\n", storeSwapDir(0), xstrerror()); - fatal_dump("Cannot cd to swap directory?"); - } - } + mainSetCwd(); /* after this point we want to see the mallinfo() output */ do_mallinfo = 1; mimeInit(Config.mimeTablePathname); @@ -444,6 +469,7 @@ #if DELAY_POOLS delayPoolsInit(); #endif + fwdInit(); } serverConnectionsOpen(); if (theOutIcpConnection >= 0) { @@ -455,7 +481,7 @@ if (!configured_once) writePidFile(); /* write PID file */ -#if (defined(_SQUID_LINUX_) && USE_ASYNC_IO) +#ifdef _SQUID_LINUX_THREADS_ squid_signal(SIGQUIT, rotate_logs, SA_RESTART); squid_signal(SIGTRAP, sigusr2_handle, SA_RESTART); #else @@ -523,17 +549,30 @@ mainParseOptions(argc, argv); + /* parse configuration file + * note: in "normal" case this used to be called from mainInitialize() */ + { + int parse_err; + if (!ConfigFile) + ConfigFile = xstrdup(DefaultConfigFile); + assert(!configured_once); + cbdataInit(); +#if USE_LEAKFINDER + leakInit(); +#endif + memInit(); /* memInit is required for config parsing */ + parse_err = parseConfigFile(ConfigFile); + + if (opt_parse_cfg_only) + return parse_err; + } + /* send signal to running copy and exit */ if (opt_send_signal != -1) { sendSignal(); /* NOTREACHED */ } if (opt_create_swap_dirs) { - if (ConfigFile == NULL) - ConfigFile = xstrdup(DefaultConfigFile); - cbdataInit(); - memInit(); /* memInit is required for config parsing */ - parseConfigFile(ConfigFile); setEffectiveUser(); debug(0, 0) ("Creating Swap Directories\n"); storeCreateSwapDirectories(); @@ -547,15 +586,16 @@ for (n = Squid_MaxFD; n > 2; n--) close(n); - /*init comm module */ + /* init comm module */ comm_init(); comm_select_init(); - /* we have to init fdstat here. */ - fd_open(0, FD_LOG, "stdin"); - fd_open(1, FD_LOG, "stdout"); - fd_open(2, FD_LOG, "stderr"); - + if (opt_no_daemon) { + /* we have to init fdstat here. */ + fd_open(0, FD_LOG, "stdin"); + fd_open(1, FD_LOG, "stdout"); + fd_open(2, FD_LOG, "stderr"); + } mainInitialize(); /* main loop */ @@ -616,11 +656,6 @@ { pid_t pid; debug_log = stderr; - if (ConfigFile == NULL) - ConfigFile = xstrdup(DefaultConfigFile); - cbdataInit(); - memInit(); - parseConfigFile(ConfigFile); pid = readPidFile(); if (pid > 1) { if (kill(pid, opt_send_signal) && @@ -652,32 +687,64 @@ int status; #endif pid_t pid; + int i; if (*(argv[0]) == '(') return; + openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4); + if ((pid = fork()) < 0) + syslog(LOG_ALERT, "fork failed: %s", xstrerror()); + else if (pid > 0) + exit(0); + if (setsid() < 0) + syslog(LOG_ALERT, "setsid failed: %s", xstrerror()); +#ifdef TIOCNOTTY + if ((i = open("/dev/tty", O_RDWR)) >= 0) { + ioctl(i, TIOCNOTTY, NULL); + close(i); + } +#endif + for (i = 0; i < Squid_MaxFD; i++) + close(i); +#if NOT_NEEDED + umask(0); +#endif for (;;) { - if (fork() == 0) { + if ((pid = fork()) == 0) { /* child */ prog = xstrdup(argv[0]); argv[0] = xstrdup("(squid)"); execvp(prog, argv); - fatal("execvp failed"); + syslog(LOG_ALERT, "execvp failed: %s", xstrerror()); } - /* parent */ time(&start); - do { - squid_signal(SIGINT, SIG_IGN, SA_RESTART); + /* parent */ + syslog(LOG_NOTICE, "Squid Parent: child process %d started", pid); + time(&start); + squid_signal(SIGINT, SIG_IGN, SA_RESTART); #ifdef _SQUID_NEXT_ - pid = wait3(&status, 0, NULL); + pid = wait3(&status, 0, NULL); #else - pid = waitpid(-1, &status, 0); + pid = waitpid(-1, &status, 0); #endif - } while (pid > 0); time(&stop); + if (WIFEXITED(status)) { + syslog(LOG_NOTICE, + "Squid Parent: child process %d exited with status %d", + pid, WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + syslog(LOG_NOTICE, + "Squid Parent: child process %d exited due to signal %d", + pid, WTERMSIG(status)); + } else { + syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid); + } if (stop - start < 10) failcount++; else failcount = 0; - if (failcount == 5) + if (failcount == 5) { + syslog(LOG_ALERT, "Exiting due to repeated, frequent failures"); exit(1); + } if (WIFEXITED(status)) if (WEXITSTATUS(status) == 0) exit(0); @@ -706,11 +773,20 @@ releaseServerSockets(); commCloseAllSockets(); unlinkdClose(); +#if USE_ASYNC_IO + aioSync(); /* flush pending object writes / unlinks */ +#endif storeDirWriteCleanLogs(0); PrintRusage(); dumpMallocStats(); +#if USE_ASYNC_IO + aioSync(); /* flush log writes */ +#endif storeLogClose(); accessLogClose(); +#if USE_ASYNC_IO + aioSync(); /* flush log close */ +#endif #if PURIFY || XMALLOC_TRACE configFreeMemory(); storeFreeMemory(); @@ -722,17 +798,20 @@ clientdbFreeMemory(); httpHeaderCleanModule(); statFreeMemory(); + eventFreeMemory(); mimeFreeMemory(); errorClean(); #endif - memClean(); #if !XMALLOC_TRACE - file_close(0); - file_close(1); - file_close(2); + if (opt_no_daemon) { + file_close(0); + file_close(1); + file_close(2); + } #endif fdDumpOpen(); fdFreeMemory(); + memClean(); #if XMALLOC_TRACE xmalloc_find_leaks(); debug(1, 0) ("Memory used after shutdown: %d\n", xmalloc_total); Index: squid/src/mem.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/mem.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/mem.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/mem.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: mem.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: mem.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 13 High Level Memory Pool Management * AUTHOR: Harvest Derived @@ -127,9 +127,9 @@ return memPoolAlloc(MemPools[type]); } -/* find appropriate pool and use it */ +/* give memory back to the pool */ void -memFree(mem_type type, void *p) +memFree(void *p, int type) { memPoolFree(MemPools[type], p); } @@ -216,6 +216,9 @@ memDataInit(MEM_COMMWRITESTATEDATA, "CommWriteStateData", sizeof(CommWriteStateData), 0); memDataInit(MEM_CONNSTATEDATA, "ConnStateData", sizeof(ConnStateData), 0); +#if USE_CACHE_DIGESTS + memDataInit(MEM_DIGEST_FETCH_STATE, "DigestFetchState", sizeof(DigestFetchState), 0); +#endif memDataInit(MEM_DISK_BUF, "Disk I/O Buffer", DISK_PAGE_SIZE, 200); memDataInit(MEM_DLINK_LIST, "dlink_list", sizeof(dlink_list), 10); memDataInit(MEM_DLINK_NODE, "dlink_node", sizeof(dlink_node), 10); @@ -257,10 +260,11 @@ memDataInit(MEM_NETDBENTRY, "netdbEntry", sizeof(netdbEntry), 0); memDataInit(MEM_NET_DB_NAME, "net_db_name", sizeof(net_db_name), 0); memDataInit(MEM_NET_DB_PEER, "net_db_peer", sizeof(net_db_peer), 0); + memDataInit(MEM_PEER, "peer", sizeof(peer), 0); #if USE_CACHE_DIGESTS + memDataInit(MEM_PEER_DIGEST, "PeerDigest", sizeof(PeerDigest), 0); memDataInit(MEM_DIGEST_FETCH_STATE, "DigestFetchState", sizeof(DigestFetchState), 0); #endif - memDataInit(MEM_PEER, "peer", sizeof(peer), 0); memDataInit(MEM_PINGERECHODATA, "pingerEchoData", sizeof(pingerEchoData), 0); memDataInit(MEM_PINGERREPLYDATA, "pingerReplyData", @@ -274,7 +278,7 @@ memDataInit(MEM_SQUIDCONFIG2, "SquidConfig2", sizeof(SquidConfig2), 0); memDataInit(MEM_STATCOUNTERS, "StatCounters", sizeof(StatCounters), 0); memDataInit(MEM_STMEM_BUF, "Store Mem Buffer", SM_PAGE_SIZE, - Config.Mem.maxSize / SM_PAGE_SIZE); + Config.memMaxSize / SM_PAGE_SIZE); memDataInit(MEM_STOREENTRY, "StoreEntry", sizeof(StoreEntry), 0); memDataInit(MEM_STORE_CLIENT, "store_client", sizeof(store_client), 0); memDataInit(MEM_SWAPDIR, "SwapDir", sizeof(SwapDir), 0); @@ -293,7 +297,7 @@ continue; /* * If you hit this assertion, then you forgot to add a - * memDataInit() line for type 't' above. + * memDataInit() line for type 't'. */ assert(MemPools[t]); } @@ -323,23 +327,23 @@ void memFree2K(void *p) { - memFree(MEM_2K_BUF, p); + memFree(p, MEM_2K_BUF); } void memFree4K(void *p) { - memFree(MEM_4K_BUF, p); + memFree(p, MEM_4K_BUF); } void memFree8K(void *p) { - memFree(MEM_8K_BUF, p); + memFree(p, MEM_8K_BUF); } void memFreeDISK(void *p) { - memFree(MEM_DISK_BUF, p); + memFree(p, MEM_DISK_BUF); } Index: squid/src/mib.txt =================================================================== RCS file: /cvsroot/squid-sf//squid/src/mib.txt,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/mib.txt 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/mib.txt 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ SQUID-MIB DEFINITIONS ::= BEGIN -- --- $Id: mib.txt,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ +-- $Id: mib.txt,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ -- IMPORTS @@ -36,24 +36,12 @@ REVISION "9809220000Z" DESCRIPTION "Move to SMIv2. Prepare to split into proxy/squid." + REVISION "9901010000Z" + DESCRIPTION + "Added objects and corrected asn.1 syntax and + descriptions." ::= { nlanr 1 } --- v 1.16 1998/09/22 glenn@ircache.net - --- --- This is a hack to get around a problem with the current --- version of the SNMP library. Remove the following seven lines --- before using with SNMP tools. --- - -org OBJECT IDENTIFIER ::= { iso 1 } -dod OBJECT IDENTIFIER ::= { org 6 } -internet OBJECT IDENTIFIER ::= { dod 1 } -private OBJECT IDENTIFIER ::= { internet 4 } -enterprises OBJECT IDENTIFIER ::= { private 1 } -nlanr OBJECT IDENTIFIER ::= { enterprises 3495 } -squid OBJECT IDENTIFIER ::= { nlanr 1 } - -- -- OID Assignments -- @@ -74,7 +62,7 @@ MAX-ACCESS read-only STATUS current DESCRIPTION - " Virtual Memory size in KB" + " Storage Mem size in KB" ::= { cacheSystem 1 } cacheSysStorage OBJECT-TYPE @@ -82,7 +70,7 @@ MAX-ACCESS read-only STATUS current DESCRIPTION - " Diskspace in KB" + " Storage Swap size in KB" ::= { cacheSystem 2 } cacheUptime OBJECT-TYPE @@ -90,7 +78,7 @@ MAX-ACCESS read-only STATUS current DESCRIPTION - " Number of timeticks since cache started " + " The Uptime of the cache in timeticks" ::= { cacheSystem 3 } -- @@ -142,48 +130,32 @@ MAX-ACCESS read-only STATUS current DESCRIPTION - " Cache Memory Maximum Size " + " The value of the cache_mem parameter in MB" ::= { cacheStorageConfig 1 } - cacheMemHighWM OBJECT-TYPE - SYNTAX Integer32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - " Cache Memory High Water Mark " - ::= { cacheStorageConfig 2 } - - cacheMemLowWM OBJECT-TYPE - SYNTAX Integer32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION - " Cache Memory Low Water Mark " - ::= { cacheStorageConfig 3 } - cacheSwapMaxSize OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current DESCRIPTION - " Cache Swap Maximum Size " - ::= { cacheStorageConfig 4 } + " The total of the cache_dir space allocated in MB" + ::= { cacheStorageConfig 2 } cacheSwapHighWM OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current DESCRIPTION - " Cache Swap High Water Mark " - ::= { cacheStorageConfig 5 } + " Cache Swap High Water Mark" + ::= { cacheStorageConfig 3 } cacheSwapLowWM OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current DESCRIPTION - " Cache Swap Low Water Mark " - ::= { cacheStorageConfig 6 } + " Cache Swap Low Water Mark" + ::= { cacheStorageConfig 4 } -- end of cacheStorageConfig group @@ -203,7 +175,7 @@ MAX-ACCESS read-only STATUS current DESCRIPTION - " Number of system page faults " + " Page faults with physical i/o" ::= { cacheSysPerf 1 } cacheSysNumReads OBJECT-TYPE @@ -211,39 +183,39 @@ MAX-ACCESS not-accessible STATUS current DESCRIPTION - " Number of Reads " + " HTTP I/O number of reads" ::= { cacheSysPerf 2 } - cacheSysDefReads OBJECT-TYPE - SYNTAX Counter32 - MAX-ACCESS not-accessible - STATUS current - DESCRIPTION - " see cachemgr " - ::= { cacheSysPerf 3 } - cacheMemUsage OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current DESCRIPTION - " Amount of system memory allocated by the cache" - ::= { cacheSysPerf 4 } + " Total memory accounted for KB" + ::= { cacheSysPerf 3 } - cacheCpuUsage OBJECT-TYPE + cacheCpuTime OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current DESCRIPTION " Amount of cpu seconds consumed" - ::= { cacheSysPerf 5 } + ::= { cacheSysPerf 4 } + + cacheCpuUsage OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " The percentage use of the CPU" + ::= { cacheSysPerf 5 } cacheMaxResSize OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current DESCRIPTION - " Maximum Resident Size" + " Maximum Resident Size in KB" ::= { cacheSysPerf 6 } cacheNumObjCount OBJECT-TYPE @@ -251,31 +223,39 @@ MAX-ACCESS read-only STATUS current DESCRIPTION - " Number of objects " + " Number of objects stored by the cache" ::= { cacheSysPerf 7 } cacheCurrentLRUExpiration OBJECT-TYPE SYNTAX TimeTicks MAX-ACCESS read-only STATUS current + DESCRIPTION + " Storage LRU Expiration Age" ::= { cacheSysPerf 8 } cacheCurrentUnlinkRequests OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Requests given to unlinkd" ::= { cacheSysPerf 9 } cacheCurrentUnusedFileDescrCount OBJECT-TYPE SYNTAX Gauge32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Available number of file descriptors" ::= { cacheSysPerf 10 } cacheCurrentReservedFileDescrCount OBJECT-TYPE SYNTAX Gauge32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Reserved number of file descriptors" ::= { cacheSysPerf 11 } -- @@ -292,86 +272,121 @@ SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Number of HTTP requests received" ::= { cacheProtoAggregateStats 1 } cacheHttpHits OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Number of HTTP Hits" ::= { cacheProtoAggregateStats 2 } cacheHttpErrors OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Number of HTTP Errors" ::= { cacheProtoAggregateStats 3 } cacheHttpInKb OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Number of HTTP KB's recieved" ::= { cacheProtoAggregateStats 4 } cacheHttpOutKb OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Number of HTTP KB's transmitted" ::= { cacheProtoAggregateStats 5 } cacheIcpPktsSent OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Number of ICP messages sent" ::= { cacheProtoAggregateStats 6 } cacheIcpPktsRecv OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Number of ICP messages received" ::= { cacheProtoAggregateStats 7 } cacheIcpKbSent OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Number of ICP KB's transmitted" ::= { cacheProtoAggregateStats 8 } cacheIcpKbRecv OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Number of ICP KB's recieved" ::= { cacheProtoAggregateStats 9 } cacheServerRequests OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " All requests from the client for the cache server" ::= { cacheProtoAggregateStats 10 } cacheServerErrors OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " All errors for the cache server from client requests" ::= { cacheProtoAggregateStats 11 } cacheServerInKb OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " KB's of traffic recieved from servers" ::= { cacheProtoAggregateStats 12 } cacheServerOutKb OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " KB's of traffic sent to servers" ::= { cacheProtoAggregateStats 13 } cacheCurrentSwapSize OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " Storage Swap size" ::= { cacheProtoAggregateStats 14 } + cacheClients OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " Number of clients accessing cache" + ::= { cacheProtoAggregateStats 15 } -- -- cacheProtoMedianSvcStats group @@ -402,57 +417,91 @@ cacheHttpHitSvcTime Integer32, cacheIcpQuerySvcTime Integer32, cacheIcpReplySvcTime Integer32, - cacheDnsSvcTime Integer32 + cacheDnsSvcTime Integer32, + cacheRequestHitRatio Integer32, + cacheRequestByteRatio Integer32 } cacheMedianTime OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " The value used to index the table 1/5/60" ::= { cacheMedianSvcEntry 1 } cacheHttpAllSvcTime OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " HTTP all service time" ::= { cacheMedianSvcEntry 2 } cacheHttpMissSvcTime OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " HTTP miss service time" ::= { cacheMedianSvcEntry 3 } cacheHttpNmSvcTime OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " HTTP near miss service time" ::= { cacheMedianSvcEntry 4 } cacheHttpHitSvcTime OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " HTTP hit service time" ::= { cacheMedianSvcEntry 5 } cacheIcpQuerySvcTime OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " ICP query service time" ::= { cacheMedianSvcEntry 6 } cacheIcpReplySvcTime OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " ICP reply service time" ::= { cacheMedianSvcEntry 7 } cacheDnsSvcTime OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-only STATUS current + DESCRIPTION + " DNS service time" ::= { cacheMedianSvcEntry 8 } + cacheRequestHitRatio OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " Request Hit Ratios" + ::= { cacheMedianSvcEntry 9 } + + cacheRequestByteRatio OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " Byte Hit Ratios" + ::= { cacheMedianSvcEntry 10 } + -- -- cacheNetwork group -- @@ -516,11 +565,6 @@ STATUS current ::= { cacheIpCache 8 } - cacheQueueLength OBJECT-TYPE - SYNTAX Gauge32 - MAX-ACCESS read-only - STATUS current - ::= { cacheIpCache 9 } -- -- cacheFqdnCache -- @@ -567,12 +611,6 @@ STATUS current ::= { cacheFqdnCache 7 } - cacheQueueLength OBJECT-TYPE - SYNTAX Gauge32 - MAX-ACCESS read-only - STATUS current - ::= { cacheFqdnCache 8 } - -- -- cacheDNS -- Index: squid/src/mime.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/mime.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/mime.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/mime.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: mime.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: mime.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 25 MIME Parsing * AUTHOR: Harvest Derived @@ -84,11 +84,11 @@ for (p = mime; *p; p += strcspn(p, "\n\r")) { if (strcmp(p, "\r\n\r\n") == 0 || strcmp(p, "\n\n") == 0) return NULL; - while (isspace(*p)) + while (xisspace(*p)) p++; if (strncasecmp(p, name, namelen)) continue; - if (!isspace(p[namelen]) && p[namelen] != ':') + if (!xisspace(p[namelen]) && p[namelen] != ':') continue; l = strcspn(p, "\n\r") + 1; if (l > GET_HDR_SZ) @@ -99,12 +99,12 @@ q += namelen; if (*q == ':') q++, got = 1; - while (isspace(*q)) + while (xisspace(*q)) q++, got = 1; if (got && prefix) { /* we could process list entries here if we had strcasestr(). */ /* make sure we did not match a part of another field-value */ - got = !strncasecmp(q, prefix, preflen) && !isalpha(q[preflen]); + got = !strncasecmp(q, prefix, preflen) && !xisalpha(q[preflen]); } if (got) { debug(25, 5) ("mime_get_header: returning '%s'\n", q); @@ -393,6 +393,7 @@ LOCAL_ARRAY(char, url, MAX_URL); char *buf; const char *type = mimeGetContentType(icon); + HttpReply *reply; if (type == NULL) fatal("Unknown icon format while reading mime.conf\n"); buf = internalLocalUri("/squid-internal-static/icons/", icon); @@ -416,21 +417,24 @@ flags, METHOD_GET); assert(e != NULL); + storeSetPublicKey(e); e->mem_obj->request = requestLink(urlParse(METHOD_GET, url)); - httpReplyReset(e->mem_obj->reply); - httpReplySetHeaders(e->mem_obj->reply, 1.0, HTTP_OK, NULL, - type, (int) sb.st_size, sb.st_mtime, squid_curtime + 86400); - httpReplySwapOut(e->mem_obj->reply, e); + httpReplyReset(reply = e->mem_obj->reply); + httpReplySetHeaders(reply, 1.0, HTTP_OK, NULL, + type, (int) sb.st_size, sb.st_mtime, -1); + reply->cache_control = httpHdrCcCreate(); + httpHdrCcSetMaxAge(reply->cache_control, 86400); + httpHeaderPutCc(&reply->header, reply->cache_control); + httpReplySwapOut(reply, e); /* read the file into the buffer and append it to store */ buf = memAllocate(MEM_4K_BUF); while ((n = read(fd, buf, 4096)) > 0) storeAppend(e, buf, n); file_close(fd); - storeSetPublicKey(e); storeComplete(e); storeTimestampsSet(e); EBIT_SET(e->flags, ENTRY_SPECIAL); debug(25, 3) ("Loaded icon %s\n", url); storeUnlockObject(e); - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); } Index: squid/src/mime.conf =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/mime.conf,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/mime.conf 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/mime.conf 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -116,6 +116,8 @@ \.mwrt$ application/macwriteii anthony-unknown.gif - image \.msw$ application/msword anthony-unknown.gif - image \.doc$ application/msword anthony-unknown.gif - image +view +\.xls$ application/msexcel anthony-unknown.gif - image +\.wk[s1234]$ application/vnd.lotus-1-2-3 anthony-unknown.gif - image \.mif$ application/x-mif anthony-unknown.gif - image \.sit$ application/stuffit anthony-unknown.gif - image \.pict$ application/pict anthony-image.gif - image @@ -127,5 +129,6 @@ README text/plain anthony-text.gif - ascii +download ^core$ application/octet-stream anthony-bomb.gif - image \.core$ application/octet-stream anthony-bomb.gif - image +\.png$ image/png anthony-image.gif - image # the default . text/plain anthony-unknown.gif - image +view +download Index: squid/src/neighbors.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/neighbors.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/neighbors.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/neighbors.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: neighbors.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: neighbors.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 15 Neighbor Routines * AUTHOR: Harvest Derived @@ -132,21 +132,22 @@ if (request->flags.need_validation) return 0; } - if (p->pinglist == NULL && p->access == NULL) + if (p->peer_domain == NULL && p->access == NULL) return do_ping; do_ping = 0; - for (d = p->pinglist; d; d = d->next) { + for (d = p->peer_domain; d; d = d->next) { if (matchDomainName(d->domain, request->host)) { do_ping = d->do_ping; break; } do_ping = !d->do_ping; } - if (p->pinglist && 0 == do_ping) + if (p->peer_domain && 0 == do_ping) return do_ping; if (p->access == NULL) return do_ping; checklist.src_addr = request->client_addr; + checklist.my_addr = request->my_addr; checklist.request = request; return aclCheckFast(p->access, &checklist); } @@ -317,7 +318,7 @@ } if (p) { *P = p->next; - peerDestroy(p); + cbdataFree(p); Config.npeers--; } first_ping = Config.peers; @@ -438,6 +439,18 @@ * last query */ p->stats.last_reply = squid_curtime; + /* + * We used to not expect a reply in this case; we assumed + * the peer was DEAD if we hadn't queried it in a long + * time. However, the number of people whining to + * squid-users that ICP is broken became unbearable. They + * tried a single request which, to their amazement, was + * forwarded directly to the origin server, even thought + * they KNEW it was in a neighbor cache. Ok, I give up, you + * win! + */ + (*exprep)++; + (*timeout) += 1000; } else if (neighborUp(p)) { /* its alive, expect a reply from it */ (*exprep)++; @@ -510,31 +523,28 @@ assert(request); debug(15, 5) ("peerDigestLookup: peer %s\n", p->host); /* does the peeer have a valid digest? */ - if (p->digest.flags.disabled) { - debug(15, 5) ("peerDigestLookup: Disabled!\n"); + if (!p->digest) { + debug(15, 5) ("peerDigestLookup: gone!\n"); return LOOKUP_NONE; } else if (!peerHTTPOkay(p, request)) { - debug(15, 5) ("peerDigestLookup: !peerHTTPOkay()\n"); + debug(15, 5) ("peerDigestLookup: !peerHTTPOkay\n"); return LOOKUP_NONE; - } else if (p->digest.flags.usable) { - debug(15, 5) ("peerDigestLookup: Usable!\n"); + } else if (p->digest->flags.usable) { + debug(15, 5) ("peerDigestLookup: usable\n"); /* fall through; put here to have common case on top */ ; - } else if (!p->digest.flags.inited) { - debug(15, 5) ("peerDigestLookup: !initialized\n"); - if (!p->digest.flags.init_pending) { - p->digest.flags.init_pending = 1; - cbdataLock(p); - eventAdd("peerDigestInit", peerDigestInit, p, 0.0, 1); - } + } else if (!p->digest->flags.needed) { + debug(15, 5) ("peerDigestLookup: note need\n"); + peerDigestNeeded(p->digest); return LOOKUP_NONE; } else { - debug(15, 5) ("peerDigestLookup: Whatever!\n"); + debug(15, 5) ("peerDigestLookup: !ready && %srequested\n", + p->digest->flags.requested ? "" : "!"); return LOOKUP_NONE; } debug(15, 5) ("peerDigestLookup: OK to lookup peer %s\n", p->host); - assert(p->digest.cd); + assert(p->digest->cd); /* does digest predict a hit? */ - if (!cacheDigestTest(p->digest.cd, key)) + if (!cacheDigestTest(p->digest->cd, key)) return LOOKUP_MISS; debug(15, 5) ("peerDigestLookup: peer %s says HIT!\n", p->host); return LOOKUP_HIT; @@ -555,7 +565,8 @@ peer *p; int p_rtt; int i; - + if (!request->flags.hierarchical) + return NULL; key = storeKeyPublic(storeUrl(entry), request->method); for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) { lookup_t lookup; @@ -844,6 +855,20 @@ return p; } +peer * +peerFindByNameAndPort(const char *name, unsigned short port) +{ + peer *p = NULL; + for (p = Config.peers; p; p = p->next) { + if (strcasecmp(name, p->host)) + continue; + if (port != p->http_port) + continue; + break; + } + return p; +} + int neighborUp(const peer * p) { @@ -857,19 +882,39 @@ } void -peerDestroy(peer * p) +peerDestroy(void *data, int unused) { + peer *p = data; struct _domain_ping *l = NULL; struct _domain_ping *nl = NULL; if (p == NULL) return; - for (l = p->pinglist; l; l = nl) { + for (l = p->peer_domain; l; l = nl) { nl = l->next; safe_free(l->domain); safe_free(l); } safe_free(p->host); - cbdataFree(p); +#if USE_CACHE_DIGESTS + if (p->digest) { + PeerDigest *pd = p->digest; + p->digest = NULL; + cbdataUnlock(pd); + } +#endif + xfree(p); +} + +void +peerNoteDigestGone(peer * p) +{ +#if USE_CACHE_DIGESTS + if (p->digest) { + PeerDigest *pd = p->digest; + p->digest = NULL; + cbdataUnlock(pd); + } +#endif } static void @@ -915,7 +960,7 @@ { peer *p = NULL; if (eventFind(peerRefreshDNS, NULL)) - return; + eventDelete(peerRefreshDNS, NULL); if (!data && 0 == stat5minClientRequests()) { /* no recent client traffic, wait a bit */ eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 180.0, 1); @@ -1012,10 +1057,9 @@ psstate->request = requestLink(urlParse(METHOD_GET, url)); psstate->entry = fake; psstate->callback = NULL; - psstate->fail_callback = NULL; psstate->callback_data = p; psstate->ping.start = current_time; - cbdataAdd(psstate, MEM_NONE); + cbdataAdd(psstate, cbdataXfree, 0); mem = fake->mem_obj; mem->request = requestLink(psstate->request); mem->start_ping = current_time; @@ -1056,7 +1100,7 @@ p->mcast.avg_n_members, p->stats.rtt); p->mcast.n_replies_expected = (int) p->mcast.avg_n_members; - fake->store_status = STORE_ABORTED; + EBIT_SET(fake->flags, ENTRY_ABORTED); requestUnlink(fake->mem_obj->request); fake->mem_obj->request = NULL; storeReleaseRequest(fake); @@ -1190,9 +1234,9 @@ storeAppendPrintf(sentry, "Last failed connect() at: %s\n", mkhttpdlogtime(&(e->last_fail_time))); } - if (e->pinglist != NULL) { + if (e->peer_domain != NULL) { storeAppendPrintf(sentry, "DOMAIN LIST: "); - for (d = e->pinglist; d; d = d->next) { + for (d = e->peer_domain; d; d = d->next) { storeAppendPrintf(sentry, "%s%s ", d->do_ping ? null_string : "!", d->domain); } Index: squid/src/net_db.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/net_db.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/net_db.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/net_db.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: net_db.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: net_db.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 38 Network Measurement Database * AUTHOR: Duane Wessels @@ -126,7 +126,7 @@ } hash_remove_link(host_table, (hash_link *) x); xfree(x->name); - memFree(MEM_NET_DB_NAME, (void *) x); + memFree((void *) x, MEM_NET_DB_NAME); } static netdbEntry * @@ -152,7 +152,7 @@ n->n_peers_alloc = 0; if (n->link_count == 0) { netdbHashDelete(n->network); - memFree(MEM_NETDBENTRY, n); + memFree(n, MEM_NETDBENTRY); } } @@ -460,7 +460,7 @@ } count++; } - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); fclose(fp); getCurrentTime(); debug(38, 1) ("NETDB state reloaded; %d entries, %d msec\n", @@ -484,7 +484,7 @@ { netdbEntry *n = data; safe_free(n->peers); - memFree(MEM_NETDBENTRY, n); + memFree(n, MEM_NETDBENTRY); } static void @@ -492,7 +492,7 @@ { net_db_name *x = data; xfree(x->name); - memFree(MEM_NET_DB_NAME, x); + memFree(x, MEM_NET_DB_NAME); } static void @@ -587,8 +587,8 @@ debug(38, 3) ("netdbExchangeHandleReply: used %d entries, (x %d bytes) == %d bytes total\n", nused, rec_sz, nused * rec_sz); debug(38, 3) ("netdbExchangeHandleReply: seen %d, used %d\n", ex->seen, ex->used); - if (ex->e->store_status == STORE_ABORTED) { - debug(38, 3) ("netdbExchangeHandleReply: STORE_ABORTED\n"); + if (EBIT_TEST(ex->e->flags, ENTRY_ABORTED)) { + debug(38, 3) ("netdbExchangeHandleReply: ENTRY_ABORTED\n"); netdbExchangeDone(ex); } else if (ex->e->store_status == STORE_PENDING) { debug(38, 3) ("netdbExchangeHandleReply: STORE_PENDING\n"); @@ -609,7 +609,7 @@ { netdbExchangeState *ex = data; debug(38, 3) ("netdbExchangeDone: %s\n", storeUrl(ex->e)); - memFree(MEM_4K_BUF, ex->buf); + memFree(ex->buf, MEM_4K_BUF); requestUnlink(ex->r); storeUnregister(ex->e, ex); storeUnlockObject(ex->e); @@ -650,7 +650,7 @@ if (n->next_ping_time > squid_curtime) return; h = xstrdup(hostname); - cbdataAdd(h, MEM_NONE); + cbdataAdd(h, cbdataXfree, 0); cbdataLock(h); ipcache_nbgethostbyname(hostname, netdbSendPing, h); #endif @@ -668,6 +668,8 @@ N = ++n->pings_recv; if (N > 5) N = 5; + if (rtt < 1.0) + rtt = 1.0; n->hops = ((n->hops * (N - 1)) + hops) / N; n->rtt = ((n->rtt * (N - 1)) + rtt) / N; debug(38, 3) ("netdbHandlePingReply: %s; rtt=%5.1f hops=%4.1f\n", @@ -932,7 +934,7 @@ } assert(0 == i); storeBufferFlush(s); - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); #else httpReplyReset(reply); httpReplySetHeaders(reply, 1.0, HTTP_BAD_REQUEST, "Bad Request", @@ -949,7 +951,7 @@ peer *p = data; char *uri; netdbExchangeState *ex = xcalloc(1, sizeof(*ex)); - cbdataAdd(ex, MEM_NONE); + cbdataAdd(ex, cbdataXfree, 0); cbdataLock(p); ex->p = p; uri = internalRemoteUri(p->host, p->http_port, "/squid-internal-dynamic/", "netdb"); @@ -971,7 +973,7 @@ storeClientCopy(ex->e, ex->seen, ex->used, ex->buf_sz, ex->buf, netdbExchangeHandleReply, ex); ex->r->flags.loopdetect = 1; /* cheat! -- force direct */ - fwdStart(-1, ex->e, ex->r, no_addr); + fwdStart(-1, ex->e, ex->r, no_addr, no_addr); #endif } Index: squid/src/pconn.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/pconn.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/pconn.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/pconn.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: pconn.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: pconn.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 48 Persistent Connections * AUTHOR: Duane Wessels @@ -181,7 +181,7 @@ int *old; LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10); LOCAL_ARRAY(char, desc, FD_DESC_SZ); - if (fdNFree() < (RESERVED_FD << 2)) { + if (fdNFree() < (RESERVED_FD << 1)) { debug(48, 3) ("pconnPush: Not many unused FDs\n"); comm_close(fd); return; Index: squid/src/peer_digest.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/peer_digest.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/peer_digest.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/peer_digest.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: peer_digest.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: peer_digest.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 72 Peer Digest Routines * AUTHOR: Alex Rousskov @@ -40,235 +40,264 @@ /* local types */ /* local prototypes */ -static void peerDigestClean(peer * p); -static time_t peerDigestNextDisDelay(const peer * p); -static time_t peerDigestExpiresDelay(const peer * p, const StoreEntry * e); -static void peerDigestDisable(peer * p); -static void peerDigestDelay(peer * p, int disable, time_t delay); -static EVH peerDigestValidate; -static void peerDigestRequest(peer * p); +static time_t peerDigestIncDelay(const PeerDigest * pd); +static time_t peerDigestNewDelay(const StoreEntry * e); +static void peerDigestSetCheck(PeerDigest * pd, time_t delay); +static void peerDigestClean(PeerDigest *); +static EVH peerDigestCheck; +static void peerDigestRequest(PeerDigest * pd); static STCB peerDigestFetchReply; -static void peerDigestRequest(peer * p); static STCB peerDigestSwapInHeaders; static STCB peerDigestSwapInCBlock; static STCB peerDigestSwapInMask; static int peerDigestFetchedEnough(DigestFetchState * fetch, char *buf, ssize_t size, const char *step_name); -static void peerDigestFetchFinish(DigestFetchState * fetch, char *buf, const char *err_msg); -static int peerDigestSetCBlock(peer * p, const char *buf); -static int peerDigestUseful(const peer * peer); -#define max_delay(t1,t2) ((t1) >= (t2) ? (t1) : (t2)) +static void peerDigestFetchStop(DigestFetchState * fetch, char *buf, const char *reason); +static void peerDigestFetchAbort(DigestFetchState * fetch, char *buf, const char *reason); +static void peerDigestReqFinish(DigestFetchState * fetch, char *buf, int, int, int, const char *reason, int err); +static void peerDigestPDFinish(DigestFetchState * fetch, int pcb_valid, int err); +static void peerDigestFetchFinish(DigestFetchState * fetch, int err); +static void peerDigestFetchSetStats(DigestFetchState * fetch); +static int peerDigestSetCBlock(PeerDigest * pd, const char *buf); +static int peerDigestUseful(const PeerDigest * pd); /* local constants */ #define StoreDigestCBlockSize sizeof(StoreDigestCBlock) -/* min interval for requesting digests from the same peer */ -static const time_t PeerDigestRequestMinGap = 5 * 60; /* seconds */ -/* min interval for requesting digests at start */ -static const time_t GlobalDigestRequestMinGap = 1 * 60; /* seconds */ +/* min interval for requesting digests from a given peer */ +static const time_t PeerDigestReqMinGap = 5 * 60; /* seconds */ +/* min interval for requesting digests (cumulative request stream) */ +static const time_t GlobDigestReqMinGap = 1 * 60; /* seconds */ /* local vars */ -static time_t global_last_req_timestamp = 0; +static time_t pd_last_req_time = 0; /* last call to Check */ -/* always call cbdataLock() before calling this! */ -void -peerDigestInit(void *data) +/* initialize peer digest */ +static void +peerDigestInit(PeerDigest * pd, peer * p) { - peer *p = data; - assert(p); - if (!cbdataValid(p)) { /* peer disappeared */ - cbdataUnlock(p); - return; - } - assert(p->digest.flags.init_pending); - assert(!p->digest.flags.inited); - assert(!p->digest.cd); - assert(SM_PAGE_SIZE == 4096); /* we use MEM_4K_BUF */ - if (p->options.no_digest) { - peerDigestClean(p); - } else { - peerDigestValidate(p); - } - p->digest.flags.inited = 1; - p->digest.flags.init_pending = 0; + assert(pd && p); + + memset(pd, 0, sizeof(*pd)); + pd->peer = p; + /* if peer disappears, we will know it's name */ + stringInit(&pd->host, p->host); + + pd->times.initialized = squid_curtime; } -/* no pending events or requests should exist when you call this */ static void -peerDigestClean(peer * p) +peerDigestClean(PeerDigest * pd) { - if (cbdataValid(p)) { - assert(!p->digest.flags.requested); - peerDigestDisable(p); - } - cbdataUnlock(p); + assert(pd); + if (pd->cd) + cacheDigestDestroy(pd->cd); + stringClean(&pd->host); } +/* allocate new peer digest, call Init, and lock everything */ +PeerDigest * +peerDigestCreate(peer * p) +{ + PeerDigest *pd; + assert(p); + + pd = memAllocate(MEM_PEER_DIGEST); + cbdataAdd(pd, memFree, MEM_PEER_DIGEST); + peerDigestInit(pd, p); + cbdataLock(pd->peer); /* we will use the peer */ + + return pd; +} + +/* call Clean and free/unlock everything */ +void +peerDigestDestroy(PeerDigest * pd) +{ + peer *p; + assert(pd); + + p = pd->peer; + pd->peer = NULL; + /* inform peer (if any) that we are gone */ + if (cbdataValid(p)) + peerNoteDigestGone(p); + cbdataUnlock(p); /* must unlock, valid or not */ + + peerDigestClean(pd); + cbdataFree(pd); +} + +/* called by peer to indicate that somebody actually needs this digest */ +void +peerDigestNeeded(PeerDigest * pd) +{ + assert(pd); + assert(!pd->flags.needed); + assert(!pd->cd); + + pd->flags.needed = 1; + pd->times.needed = squid_curtime; + peerDigestSetCheck(pd, 0); /* check asap */ +} + +/* currently we do not have a reason to disable without destroying */ +#if FUTURE_CODE /* disables peer for good */ static void -peerDigestDisable(peer * p) +peerDigestDisable(PeerDigest * pd) { - peerDigestDelay(p, 1, -1); + debug(72, 2) ("peerDigestDisable: peer %s disabled for good\n", + strBuf(pd->host)); + pd->times.disabled = squid_curtime; + pd->times.next_check = -1; /* never */ + pd->flags.usable = 0; + + if (pd->cd) { + cacheDigestDestroy(pd->cd); + pd->cd = NULL; + } + /* we do not destroy the pd itself to preserve its "history" and stats */ } +#endif -/* next delay for a disabled entry */ +/* increment retry delay [after an unsuccessful attempt] */ static time_t -peerDigestNextDisDelay(const peer * p) +peerDigestIncDelay(const PeerDigest * pd) { - assert(p); - return p->digest.last_dis_delay ? - 2 * p->digest.last_dis_delay : /* exponential backoff */ - PeerDigestRequestMinGap; /* minimal delay */ + assert(pd); + return pd->times.retry_delay > 0 ? + 2 * pd->times.retry_delay : /* exponential backoff */ + PeerDigestReqMinGap; /* minimal delay */ } -/* artificially increases expires to avoid race conditions */ +/* artificially increases Expires: setting to avoid race conditions + * returns the delay till that [increased] expiration time */ static time_t -peerDigestExpiresDelay(const peer * p, const StoreEntry * e) +peerDigestNewDelay(const StoreEntry * e) { - assert(p); - if (!e) - return 0; + assert(e); if (e->expires > 0) - return e->expires + PeerDigestRequestMinGap - squid_curtime; - return PeerDigestRequestMinGap; + return e->expires + PeerDigestReqMinGap - squid_curtime; + return PeerDigestReqMinGap; } - -/* delays/disables digest for a psecified delay (disables forever if negative delay) */ +/* registers next digest verification */ static void -peerDigestDelay(peer * p, int disable, time_t delay) +peerDigestSetCheck(PeerDigest * pd, time_t delay) { - assert(p); - if (disable) { - p->digest.flags.disabled = 1; - p->digest.last_dis_delay = delay; - } - if (delay >= 0) { - assert(delay || !disable); - debug(72, 2) ("peerDigestDelay: %s: peer %s for %d secs till %s\n", - disable ? "disabling" : "delaying", - p->host ? p->host : " ", - delay, mkrfc1123(squid_curtime + delay)); - eventAdd("peerDigestValidate", peerDigestValidate, p, (double) delay, 1); + eventAdd("peerDigestCheck", peerDigestCheck, pd, (double) delay, 1); + pd->times.next_check = squid_curtime + delay; + debug(72, 3) ("peerDigestSetCheck: will check peer %s in %d secs\n", + strBuf(pd->host), delay); +} + +/* + * called when peer is about to disappear or have already disappeared + */ +void +peerDigestNotePeerGone(PeerDigest * pd) +{ + if (pd->flags.requested) { + debug(72, 2) ("peerDigest: peer %s gone, will destroy after fetch.\n", + strBuf(pd->host)); + /* do nothing now, the fetching chain will notice and take action */ } else { - assert(disable); - debug(72, 2) ("peerDigestDisable: disabling peer %s for good\n", - p->host ? p->host : " "); - /* just in case, will not need it anymore */ - p->digest.flags.usable = 0; + debug(72, 2) ("peerDigest: peer %s is gone, destroying now.\n", + strBuf(pd->host)); + peerDigestDestroy(pd); } } -/* request new digest if our copy is too old; schedule next validation */ +/* callback for eventAdd() (with peer digest locked) + * request new digest if our copy is too old or if we lack one; + * schedule next check otherwise */ static void -peerDigestValidate(void *data) +peerDigestCheck(void *data) { - peer *p = data; - StoreEntry *e = NULL; - int do_request; - time_t req_time = squid_curtime; - assert(p); - if (!cbdataValid(p)) { - peerDigestClean(p); + PeerDigest *pd = data; + time_t req_time; + + /* + * you can't assert(cbdataValid(pd)) -- if its not valid this + * function never gets called + */ + assert(!pd->flags.requested); + + pd->times.next_check = 0; /* unknown */ + + if (!cbdataValid(pd->peer)) { + peerDigestNotePeerGone(pd); return; } - debug(72, 3) ("peerDigestValidate: digest %s\n", p->host); - debug(72, 3) ("current GMT time: %s\n", mkrfc1123(squid_curtime)); - assert(!p->digest.flags.requested); - debug(72, 3) ("peerDigestValidate: %s was %s disabled\n", - p->host, p->digest.last_dis_delay ? "" : "not"); - if (1 /* p->digest.cd */ ) { - const cache_key *key; - const char *u = internalRemoteUri(p->host, p->http_port, "/squid-internal-periodic/", StoreDigestUrlPath); - key = storeKeyPublic(u, METHOD_GET); - e = storeGet(key); - debug(72, 3) ("peerDigestValidate: %s store entry, key: %s, exp: %s\n", - e ? "has" : "no", storeKeyText(key), mkrfc1123(e ? e->expires : 0)); - } - /* currently we rely on entry->expire information */ - { - const int loaded = p->digest.cd != NULL; - const time_t exp_delay = loaded ? peerDigestExpiresDelay(p, e) : 0; - do_request = exp_delay <= 0; - req_time = squid_curtime + exp_delay; - if (req_time < squid_curtime) - req_time = squid_curtime; - } - /* do not request too often from one peer */ - if (req_time - p->digest.last_req_timestamp < PeerDigestRequestMinGap) { - if (do_request) { - debug(72, 2) ("peerDigestValidate: %s, avoiding too close peer requests (%d secs).\n", - p->host, req_time - p->digest.last_req_timestamp); - do_request = 0; - } - req_time = p->digest.last_req_timestamp + PeerDigestRequestMinGap; - } - /* at start, do not request too often from all peers */ - if (!p->digest.flags.inited && - req_time - global_last_req_timestamp < GlobalDigestRequestMinGap) { - if (do_request) { - debug(72, 2) ("peerDigestValidate: %s, avoiding too close requests (%d secs).\n", - p->host, req_time - global_last_req_timestamp); - do_request = 0; - } - req_time = global_last_req_timestamp + GlobalDigestRequestMinGap; - /* otherwise we have all but one peer returning at the same moment @?@ */ - debug(72, 5) ("peerDigestValidate: inc req_time (%+d) in anticipation of more reqs\n", - (int) (req_time - global_last_req_timestamp)); - global_last_req_timestamp = req_time; - } - /* start request if needed */ - if (do_request) { - static int nest_level = 0; - nest_level++; - assert(nest_level == 1); - debug(72, 2) ("peerDigestValidate: %s requesting; old entry expires: %s\n", - p->host, e ? mkrfc1123(e->expires) : "no entry"); - /* will eventually disable digests or call peerDigest Delay */ - peerDigestRequest(p); - nest_level--; - } else { - /* schedule next re-validation */ - assert(req_time > squid_curtime); - peerDigestDelay(p, !p->digest.cd, req_time - squid_curtime); - } + debug(72, 3) ("peerDigestCheck: peer %s:%d\n", pd->peer->host, pd->peer->http_port); + debug(72, 3) ("peerDigestCheck: time: %d, last received: %d (%+d)\n", + squid_curtime, pd->times.received, (squid_curtime - pd->times.received)); + + /* decide when we should send the request: + * request now unless too close to other requests */ + req_time = squid_curtime; + + /* per-peer limit */ + if (req_time - pd->times.received < PeerDigestReqMinGap) { + debug(72, 2) ("peerDigestCheck: %s, avoiding close peer requests (%d < %d secs).\n", + strBuf(pd->host), req_time - pd->times.received, + PeerDigestReqMinGap); + req_time = pd->times.received + PeerDigestReqMinGap; + } + /* global limit */ + if (req_time - pd_last_req_time < GlobDigestReqMinGap) { + debug(72, 2) ("peerDigestCheck: %s, avoiding close requests (%d < %d secs).\n", + strBuf(pd->host), req_time - pd_last_req_time, + GlobDigestReqMinGap); + req_time = pd_last_req_time + GlobDigestReqMinGap; + } + if (req_time <= squid_curtime) + peerDigestRequest(pd); /* will set pd->flags.requested */ + else + peerDigestSetCheck(pd, req_time - squid_curtime); } -/* ask peer cache for a fresh digest */ +/* ask store for a digest */ static void -peerDigestRequest(peer * p) +peerDigestRequest(PeerDigest * pd) { + peer *p = pd->peer; StoreEntry *e, *old_e; char *url; const cache_key *key; request_t *req; DigestFetchState *fetch = NULL; - assert(p); - p->digest.flags.requested = 1; + + pd->req_result = NULL; + pd->flags.requested = 1; + /* compute future request components */ - url = internalRemoteUri(p->host, p->http_port, "/squid-internal-periodic/", StoreDigestUrlPath); + url = internalRemoteUri(p->host, p->http_port, "/squid-internal-periodic/", StoreDigestFileName); key = storeKeyPublic(url, METHOD_GET); debug(72, 2) ("peerDigestRequest: %s key: %s\n", url, storeKeyText(key)); req = urlParse(METHOD_GET, url); - if (NULL == req) { - debug(72, 1) ("peerDigestRequest: Bad URI: %s\n", url); - return; /* @?@ */ - } + assert(req); + /* add custom headers */ assert(!req->header.len); httpHeaderPutStr(&req->header, HDR_ACCEPT, StoreDigestMimeStr); httpHeaderPutStr(&req->header, HDR_ACCEPT, "text/html"); + /* create fetch state structure */ fetch = memAllocate(MEM_DIGEST_FETCH_STATE); - cbdataAdd(fetch, MEM_DIGEST_FETCH_STATE); - cbdataLock(fetch); + cbdataAdd(fetch, memFree, MEM_DIGEST_FETCH_STATE); fetch->request = requestLink(req); - fetch->peer = p; + fetch->pd = pd; + fetch->offset = 0; + + /* update timestamps */ fetch->start_time = squid_curtime; - p->digest.last_req_timestamp = squid_curtime; - global_last_req_timestamp = squid_curtime; + pd->times.requested = squid_curtime; + pd_last_req_time = squid_curtime; + req->flags.cachable = 1; /* the rest is based on clientProcessExpired() */ req->flags.refresh = 1; @@ -280,38 +309,43 @@ storeClientListAdd(old_e, fetch); } e = fetch->entry = storeCreateEntry(url, url, req->flags, req->method); - debug(72, 5) ("peerDigestRequest: new entry is private: %d\n", - (int) EBIT_TEST(e->flags, KEY_PRIVATE)); + assert(EBIT_TEST(e->flags, KEY_PRIVATE)); storeClientListAdd(e, fetch); /* set lastmod to trigger IMS request if possible */ if (old_e) e->lastmod = old_e->lastmod; - fetch->offset = 0; - debug(72, 3) ("peerDigestRequest: forwarding to fwdStart...\n"); + /* push towards peer cache */ - fwdStart(-1, e, req, no_addr); - storeClientCopy(e, 0, 0, SM_PAGE_SIZE, memAllocate(MEM_4K_BUF), + debug(72, 3) ("peerDigestRequest: forwarding to fwdStart...\n"); + fwdStart(-1, e, req, no_addr, no_addr); + cbdataLock(fetch); + cbdataLock(fetch->pd); + storeClientCopy(e, 0, 0, 4096, memAllocate(MEM_4K_BUF), peerDigestFetchReply, fetch); } -/* waits for full http headers to be received and parses them */ +/* wait for full http headers to be received then parse them */ static void peerDigestFetchReply(void *data, char *buf, ssize_t size) { DigestFetchState *fetch = data; - peer *peer = fetch->peer; - assert(peer && buf); + PeerDigest *pd = fetch->pd; + assert(pd && buf); assert(!fetch->offset); + if (peerDigestFetchedEnough(fetch, buf, size, "peerDigestFetchReply")) return; + if (headersEnd(buf, size)) { http_status status; HttpReply *reply = fetch->entry->mem_obj->reply; assert(reply); httpReplyParse(reply, buf); status = reply->sline.status; - debug(72, 3) ("peerDigestFetchReply: %s status: %d, expires: %s\n", - peer->host, status, mkrfc1123(reply->expires)); + debug(72, 3) ("peerDigestFetchReply: %s status: %d, expires: %d (%+d)\n", + strBuf(pd->host), status, + reply->expires, reply->expires - squid_curtime); + /* this "if" is based on clientHandleIMSReply() */ if (status == HTTP_NOT_MODIFIED) { request_t *r = NULL; @@ -325,25 +359,16 @@ storeTimestampsSet(fetch->old_entry); /* get rid of 304 reply */ storeUnregister(fetch->entry, fetch); - /* paranoid assert: storeUnregister should not call us recursively */ - assert(fetch->entry); storeUnlockObject(fetch->entry); fetch->entry = fetch->old_entry; fetch->old_entry = NULL; /* preserve request -- we need its size to update counters */ /* requestUnlink(r); */ /* fetch->entry->mem_obj->request = NULL; */ - assert(fetch->entry->mem_obj); - /* kludge to make peerDigestFetchFinish think that we - * fetched the whole thing while we are reusing old digest */ - if (fetch->peer->digest.cd) { - assert(!fetch->mask_offset); - fetch->mask_offset = peer->digest.cd->mask_size; - } } else if (status == HTTP_OK) { /* get rid of old entry if any */ if (fetch->old_entry) { - debug(72, 3) ("peerDigestFetchReply: got new digest, requesting release of old digest\n"); + debug(72, 3) ("peerDigestFetchReply: got new digest, releasing old one\n"); storeUnregister(fetch->old_entry, fetch); storeReleaseRequest(fetch->old_entry); storeUnlockObject(fetch->old_entry); @@ -351,21 +376,20 @@ } } else { /* some kind of a bug */ - peerDigestFetchFinish(fetch, buf, httpStatusLineReason(&reply->sline)); + peerDigestFetchAbort(fetch, buf, httpStatusLineReason(&reply->sline)); return; } /* must have a ready-to-use store entry if we got here */ - /* can we stay with the old digest? */ - if (status == HTTP_NOT_MODIFIED && fetch->peer->digest.cd) - peerDigestFetchFinish(fetch, buf, NULL); + /* can we stay with the old in-memory digest? */ + if (status == HTTP_NOT_MODIFIED && fetch->pd->cd) + peerDigestFetchStop(fetch, buf, "Not modified"); else storeClientCopy(fetch->entry, /* have to swap in */ 0, 0, SM_PAGE_SIZE, buf, peerDigestSwapInHeaders, fetch); - return; } else { /* need more data, do we have space? */ if (size >= SM_PAGE_SIZE) - peerDigestFetchFinish(fetch, buf, "too big header"); + peerDigestFetchAbort(fetch, buf, "reply header too big"); else storeClientCopy(fetch->entry, size, 0, SM_PAGE_SIZE, buf, peerDigestFetchReply, fetch); @@ -377,12 +401,11 @@ peerDigestSwapInHeaders(void *data, char *buf, ssize_t size) { DigestFetchState *fetch = data; - peer *peer; size_t hdr_size; + if (peerDigestFetchedEnough(fetch, buf, size, "peerDigestSwapInHeaders")) return; - peer = fetch->peer; - assert(peer && buf); + assert(!fetch->offset); if ((hdr_size = headersEnd(buf, size))) { assert(fetch->entry->mem_obj->reply); @@ -390,8 +413,8 @@ httpReplyParse(fetch->entry->mem_obj->reply, buf); if (fetch->entry->mem_obj->reply->sline.status != HTTP_OK) { debug(72, 1) ("peerDigestSwapInHeaders: %s status %d got cached!\n", - peer->host, fetch->entry->mem_obj->reply->sline.status); - peerDigestFetchFinish(fetch, buf, "internal status error"); + strBuf(fetch->pd->host), fetch->entry->mem_obj->reply->sline.status); + peerDigestFetchAbort(fetch, buf, "internal status error"); return; } fetch->offset += hdr_size; @@ -401,7 +424,7 @@ } else { /* need more data, do we have space? */ if (size >= SM_PAGE_SIZE) - peerDigestFetchFinish(fetch, buf, "too big stored header"); + peerDigestFetchAbort(fetch, buf, "stored header too big"); else storeClientCopy(fetch->entry, size, 0, SM_PAGE_SIZE, buf, peerDigestSwapInHeaders, fetch); @@ -412,33 +435,36 @@ peerDigestSwapInCBlock(void *data, char *buf, ssize_t size) { DigestFetchState *fetch = data; + if (peerDigestFetchedEnough(fetch, buf, size, "peerDigestSwapInCBlock")) return; + if (size >= StoreDigestCBlockSize) { - peer *peer = fetch->peer; + PeerDigest *pd = fetch->pd; HttpReply *rep = fetch->entry->mem_obj->reply; const int seen = fetch->offset + size; - assert(peer && rep); - if (peerDigestSetCBlock(peer, buf)) { + assert(pd && rep); + if (peerDigestSetCBlock(pd, buf)) { + /* XXX: soon we will have variable header size */ fetch->offset += StoreDigestCBlockSize; - /* switch to CD buffer */ - memFree(MEM_4K_BUF, buf); + /* switch to CD buffer and fetch digest guts */ + memFree(buf, MEM_4K_BUF); buf = NULL; - assert(peer->digest.cd->mask); + assert(pd->cd->mask); storeClientCopy(fetch->entry, seen, fetch->offset, - peer->digest.cd->mask_size, - peer->digest.cd->mask, + pd->cd->mask_size, + pd->cd->mask, peerDigestSwapInMask, fetch); } else { - peerDigestFetchFinish(fetch, buf, "invalid digest cblock"); + peerDigestFetchAbort(fetch, buf, "invalid digest cblock"); } } else { /* need more data, do we have space? */ if (size >= SM_PAGE_SIZE) - peerDigestFetchFinish(fetch, buf, "too big cblock"); + peerDigestFetchAbort(fetch, buf, "digest cblock too big"); else storeClientCopy(fetch->entry, size, 0, SM_PAGE_SIZE, buf, peerDigestSwapInCBlock, fetch); @@ -449,107 +475,206 @@ peerDigestSwapInMask(void *data, char *buf, ssize_t size) { DigestFetchState *fetch = data; - peer *peer; - HttpReply *rep; - size_t buf_sz; - /* - * NOTE! buf points to the middle of peer->digest.cd->mask! - */ + PeerDigest *pd; + + /* NOTE! buf points to the middle of pd->cd->mask! */ if (peerDigestFetchedEnough(fetch, NULL, size, "peerDigestSwapInMask")) return; - peer = fetch->peer; - rep = fetch->entry->mem_obj->reply; - assert(peer && rep); - assert(peer->digest.cd && peer->digest.cd->mask); + pd = fetch->pd; + assert(pd->cd && pd->cd->mask); fetch->offset += size; fetch->mask_offset += size; - if (fetch->mask_offset >= peer->digest.cd->mask_size) { + if (fetch->mask_offset >= pd->cd->mask_size) { debug(72, 2) ("peerDigestSwapInMask: Done! Got %d, expected %d\n", - fetch->mask_offset, peer->digest.cd->mask_size); - assert(fetch->mask_offset == peer->digest.cd->mask_size); - peerDigestFetchFinish(fetch, NULL, NULL); - return; + fetch->mask_offset, pd->cd->mask_size); + assert(fetch->mask_offset == pd->cd->mask_size); + assert(peerDigestFetchedEnough(fetch, NULL, 0, "peerDigestSwapInMask")); + } else { + const size_t buf_sz = pd->cd->mask_size - fetch->mask_offset; + assert(buf_sz > 0); + storeClientCopy(fetch->entry, + fetch->offset, + fetch->offset, + buf_sz, + pd->cd->mask + fetch->mask_offset, + peerDigestSwapInMask, fetch); } - buf_sz = peer->digest.cd->mask_size - fetch->mask_offset; - assert(buf_sz > 0); - storeClientCopy(fetch->entry, - fetch->offset, - fetch->offset, - buf_sz, - peer->digest.cd->mask + fetch->mask_offset, - peerDigestSwapInMask, fetch); } static int peerDigestFetchedEnough(DigestFetchState * fetch, char *buf, ssize_t size, const char *step_name) { - const char *reason = NULL; - const char *no_bug = NULL; + PeerDigest *pd = NULL; + const char *host = " "; /* peer host */ + const char *reason = NULL; /* reason for completion */ + const char *no_bug = NULL; /* successful completion if set */ const int fcb_valid = cbdataValid(fetch); - const int pcb_valid = fcb_valid && cbdataValid(fetch->peer); + const int pdcb_valid = fcb_valid && cbdataValid(fetch->pd); + const int pcb_valid = pdcb_valid && cbdataValid(fetch->pd->peer); - if (pcb_valid) - debug(72, 6) ("%s: %s offset: %d size: %d.\n", - step_name, fetch->peer->host, fetch->offset, size); - - - /* test exiting conditions */ - if (!fcb_valid) - reason = "fetch aborted?"; - else if (!pcb_valid) - reason = "peer disappeared"; - else if (size < 0) - reason = "swap failure"; - else if (!size) - reason = no_bug = "eof"; - else if (!fetch->entry) - reason = "swap abort(?)"; - else if (fetch->entry->store_status == STORE_ABORTED) - reason = "swap abort"; + /* test possible exiting conditions (the same for most steps!) + * cases marked with '?!' should not happen */ - /* report exit reason */ + if (!reason) { + if (!fcb_valid) + reason = "fetch aborted?!"; + else if (!(pd = fetch->pd)) + reason = "peer digest disappeared?!"; +#if DONT + else if (!cbdataValid(pd)) + reason = "invalidated peer digest?!"; +#endif + else + host = strBuf(pd->host); + } + debug(72, 6) ("%s: peer %s, offset: %d size: %d.\n", + step_name, host, fcb_valid ? fetch->offset : -1, size); + + /* continue checking (with pd and host known and valid) */ + if (!reason) { + if (!cbdataValid(pd->peer)) + reason = "peer disappeared"; + else if (size < 0) + reason = "swap failure"; + else if (!fetch->entry) + reason = "swap aborted?!"; + else if (EBIT_TEST(fetch->entry->flags, ENTRY_ABORTED)) + reason = "swap aborted"; + } + /* continue checking (maybe-successful eof case) */ + if (!reason && !size) { + if (!pd->cd) + reason = "null digest?!"; + else if (fetch->mask_offset != pd->cd->mask_size) + reason = "premature end of digest?!"; + else if (!peerDigestUseful(pd)) + reason = "useless digest"; + else + reason = no_bug = "success"; + } + /* finish if we have a reason */ if (reason) { - debug(72, pcb_valid ? 3 : 1) ("%s: exiting on %s\n", step_name, reason); - if (pcb_valid) { - peerDigestFetchFinish(fetch, buf, no_bug ? NULL : reason); + const int level = strstr(reason, "?!") ? 1 : 3; + debug(72, level) ("%s: peer %s, exiting after '%s'\n", + step_name, host, reason); + peerDigestReqFinish(fetch, buf, + fcb_valid, pdcb_valid, pcb_valid, reason, !no_bug); + } else { + /* paranoid check */ + assert(fcb_valid && pdcb_valid && pcb_valid); + } + return reason != NULL; +} + +/* call this when all callback data is valid and fetch must be stopped but + * no error has occurred (e.g. we received 304 reply and reuse old digest) */ +static void +peerDigestFetchStop(DigestFetchState * fetch, char *buf, const char *reason) +{ + assert(reason); + debug(72, 2) ("peerDigestFetchStop: peer %s, reason: %s\n", + strBuf(fetch->pd->host), reason); + peerDigestReqFinish(fetch, buf, 1, 1, 1, reason, 0); +} + +/* call this when all callback data is valid but something bad happened */ +static void +peerDigestFetchAbort(DigestFetchState * fetch, char *buf, const char *reason) +{ + assert(reason); + debug(72, 2) ("peerDigestFetchAbort: peer %s, reason: %s\n", + strBuf(fetch->pd->host), reason); + peerDigestReqFinish(fetch, buf, 1, 1, 1, reason, 1); +} + +/* complete the digest transfer, update stats, unlock/release everything */ +static void +peerDigestReqFinish(DigestFetchState * fetch, char *buf, + int fcb_valid, int pdcb_valid, int pcb_valid, + const char *reason, int err) +{ + assert(reason); + + /* must go before peerDigestPDFinish */ + if (pdcb_valid) { + fetch->pd->flags.requested = 0; + fetch->pd->req_result = reason; + } + /* schedule next check if peer is still out there */ + if (pcb_valid) { + PeerDigest *pd = fetch->pd; + if (err) { + pd->times.retry_delay = peerDigestIncDelay(pd); + peerDigestSetCheck(pd, pd->times.retry_delay); } else { - /* XXX: this is probably wrong, but - * !fcb_valid implies !pcb_valid so we cannot access peer cbdata */ - if (fcb_valid) { - cbdataUnlock(fetch); - cbdataFree(fetch); - } else { - cbdataUnlock(fetch); - } + pd->times.retry_delay = 0; + peerDigestSetCheck(pd, peerDigestNewDelay(fetch->entry)); } } - return reason != NULL; + /* note: order is significant */ + if (fcb_valid) + peerDigestFetchSetStats(fetch); + if (pdcb_valid) + peerDigestPDFinish(fetch, pcb_valid, err); + if (fcb_valid) + peerDigestFetchFinish(fetch, err); + if (buf) + memFree(buf, MEM_4K_BUF); } -/* free state structures, disables digest on error - * must be called only when peer and fetch cbdata's are valid */ + +/* destroys digest if peer disappeared + * must be called only when fetch and pd cbdata are valid */ static void -peerDigestFetchFinish(DigestFetchState * fetch, char *buf, const char *err_msg) +peerDigestPDFinish(DigestFetchState * fetch, int pcb_valid, int err) { - peer *peer = fetch->peer; - MemObject *mem = fetch->entry->mem_obj; - const time_t expires = fetch->entry->expires; - const time_t fetch_resp_time = squid_curtime - fetch->start_time; - const int b_read = (fetch->entry->store_status == STORE_PENDING) ? - mem->inmem_hi : mem->object_sz; - const int req_len = fetch->request ? httpRequestPrefixLen(fetch->request) : 0; - assert(fetch->request); - /* final checks */ - if (!err_msg) { - if (!peer->digest.cd) - err_msg = "null digest (internal bug?)"; - else if (fetch->mask_offset != peer->digest.cd->mask_size) - err_msg = "premature eof"; - else if (!peerDigestUseful(peer)) - err_msg = "useless digest"; + PeerDigest *pd = fetch->pd; + const char *host = strBuf(pd->host); + + pd->times.received = squid_curtime; + pd->times.req_delay = fetch->resp_time; + kb_incr(&pd->stats.sent.kbytes, (size_t) fetch->sent.bytes); + kb_incr(&pd->stats.recv.kbytes, (size_t) fetch->recv.bytes); + pd->stats.sent.msgs += fetch->sent.msg; + pd->stats.recv.msgs += fetch->recv.msg; + + if (err) { + debug(72, 1) ("%sdisabling (%s) digest from %s\n", + pcb_valid ? "temporary " : "", + pd->req_result, host); + + if (pd->cd) { + cacheDigestDestroy(pd->cd); + pd->cd = NULL; + } + pd->flags.usable = 0; + + if (!pcb_valid) + peerDigestNotePeerGone(pd); + } else { + assert(pcb_valid); + + pd->flags.usable = 1; + + /* XXX: ugly condition, but how? */ + if (fetch->entry->store_status == STORE_OK) + debug(72, 2) ("re-used old digest from %s\n", host); + else + debug(72, 2) ("received valid digest from %s\n", host); } + fetch->pd = NULL; + cbdataUnlock(pd); +} + +/* free fetch state structures + * must be called only when fetch cbdata is valid */ +static void +peerDigestFetchFinish(DigestFetchState * fetch, int err) +{ + assert(fetch->entry && fetch->request); + if (fetch->old_entry) { debug(72, 2) ("peerDigestFetchFinish: deleting old entry\n"); storeUnregister(fetch->old_entry, fetch); @@ -557,74 +682,57 @@ storeUnlockObject(fetch->old_entry); fetch->old_entry = NULL; } - assert(fetch->entry); - debug(72, 3) ("peerDigestFetchFinish: %s, read %d b, expires: %s lmt: %s\n", - peer->host, b_read, - mkrfc1123(fetch->entry->expires), mkrfc1123(fetch->entry->lastmod)); - if (err_msg) { - debug(72, 1) ("disabling corrupted (%s) digest from %s\n", - err_msg, peer->host); - if (peer->digest.cd) { - cacheDigestDestroy(peer->digest.cd); - peer->digest.cd = NULL; - } - /* disable for a while */ - peer->digest.flags.usable = 0; - peerDigestDelay(peer, 1, - max_delay( - peerDigestExpiresDelay(peer, fetch->entry), - peerDigestNextDisDelay(peer))); - /* release buggy entry */ - storeReleaseRequest(fetch->entry); - } else { - /* ugly condition, but how? */ - if (fetch->entry->store_status == STORE_OK) { - debug(72, 2) ("re-used old digest from %s\n", peer->host); - } else { - debug(72, 2) ("received valid digest from %s\n", peer->host); - } - peer->digest.flags.usable = 1; - peer->digest.flags.disabled = 0; - peer->digest.last_dis_delay = 0; - peerDigestDelay(peer, 0, - max_delay(peerDigestExpiresDelay(peer, fetch->entry), 0)); - } /* update global stats */ - /* note: outgoing numbers are not precise! @?@ */ - kb_incr(&Counter.cd.kbytes_sent, req_len); - kb_incr(&Counter.cd.kbytes_recv, (size_t) b_read); - Counter.cd.msgs_sent++; - Counter.cd.msgs_recv++; - /* update peer stats */ - kb_incr(&peer->digest.stats.kbytes_sent, req_len); - kb_incr(&peer->digest.stats.kbytes_recv, (size_t) b_read); - peer->digest.stats.msgs_sent++; - peer->digest.stats.msgs_recv++; + kb_incr(&Counter.cd.kbytes_sent, (size_t) fetch->sent.bytes); + kb_incr(&Counter.cd.kbytes_recv, (size_t) fetch->recv.bytes); + Counter.cd.msgs_sent += fetch->sent.msg; + Counter.cd.msgs_recv += fetch->recv.msg; + /* unlock everything */ storeUnregister(fetch->entry, fetch); storeUnlockObject(fetch->entry); requestUnlink(fetch->request); fetch->entry = NULL; fetch->request = NULL; + assert(fetch->pd == NULL); cbdataUnlock(fetch); cbdataFree(fetch); - fetch = NULL; - if (buf) - memFree(MEM_4K_BUF, buf); - buf = NULL; - /* set it here and in peerDigestRequest to protect against long downloads */ - peer->digest.last_req_timestamp = squid_curtime; - peer->digest.last_fetch_resp_time = fetch_resp_time; - peer->digest.flags.requested = 0; - debug(72, 2) ("peerDigestFetchFinish: %s done; took: %d secs; expires: %s\n", - peer->host, fetch_resp_time, mkrfc1123(expires)); } +/* calculate fetch stats after completion */ +static void +peerDigestFetchSetStats(DigestFetchState * fetch) +{ + MemObject *mem; + assert(fetch->entry && fetch->request); + + mem = fetch->entry->mem_obj; + assert(mem); + + /* XXX: outgoing numbers are not precise */ + /* XXX: we must distinguish between 304 hits and misses here */ + fetch->sent.bytes = httpRequestPrefixLen(fetch->request); + fetch->recv.bytes = fetch->entry->store_status == STORE_PENDING ? + mem->inmem_hi : mem->object_sz; + fetch->sent.msg = fetch->recv.msg = 1; + fetch->expires = fetch->entry->expires; + fetch->resp_time = squid_curtime - fetch->start_time; + + debug(72, 3) ("peerDigestFetchFinish: recv %d bytes in %d secs\n", + fetch->recv.bytes, fetch->resp_time); + debug(72, 3) ("peerDigestFetchFinish: expires: %d (%+d), lmt: %d (%+d)\n", + fetch->expires, fetch->expires - squid_curtime, + fetch->entry->lastmod, fetch->entry->lastmod - squid_curtime); +} + + static int -peerDigestSetCBlock(peer * peer, const char *buf) +peerDigestSetCBlock(PeerDigest * pd, const char *buf) { StoreDigestCBlock cblock; int freed_size = 0; + const char *host = strBuf(pd->host); + xmemcpy(&cblock, buf, sizeof(cblock)); /* network -> host conversions */ cblock.ver.current = ntohs(cblock.ver.current); @@ -634,76 +742,128 @@ cblock.del_count = ntohl(cblock.del_count); cblock.mask_size = ntohl(cblock.mask_size); debug(72, 2) ("got digest cblock from %s; ver: %d (req: %d)\n", - peer->host, (int) cblock.ver.current, (int) cblock.ver.required); + host, (int) cblock.ver.current, (int) cblock.ver.required); debug(72, 2) ("\t size: %d bytes, e-cnt: %d, e-util: %d%%\n", cblock.mask_size, cblock.count, xpercentInt(cblock.count, cblock.capacity)); /* check version requirements (both ways) */ if (cblock.ver.required > CacheDigestVer.current) { debug(72, 1) ("%s digest requires version %d; have: %d\n", - peer->host, cblock.ver.required, CacheDigestVer.current); + host, cblock.ver.required, CacheDigestVer.current); return 0; } if (cblock.ver.current < CacheDigestVer.required) { debug(72, 1) ("%s digest is version %d; we require: %d\n", - peer->host, cblock.ver.current, CacheDigestVer.required); + host, cblock.ver.current, CacheDigestVer.required); return 0; } /* check consistency */ if (cblock.ver.required > cblock.ver.current || cblock.mask_size <= 0 || cblock.capacity <= 0 || cblock.bits_per_entry <= 0 || cblock.hash_func_count <= 0) { - debug(72, 0) ("%s digest cblock is corrupted.\n", peer->host); + debug(72, 0) ("%s digest cblock is corrupted.\n", host); return 0; } /* check consistency further */ if (cblock.mask_size != cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry)) { debug(72, 0) ("%s digest cblock is corrupted (mask size mismatch: %d ? %d).\n", - peer->host, cblock.mask_size, cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry)); + host, cblock.mask_size, cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry)); return 0; } /* there are some things we cannot do yet */ if (cblock.hash_func_count != CacheDigestHashFuncCount) { debug(72, 0) ("%s digest: unsupported #hash functions: %d ? %d.\n", - peer->host, cblock.hash_func_count, CacheDigestHashFuncCount); + host, cblock.hash_func_count, CacheDigestHashFuncCount); return 0; } /* * no cblock bugs below this point */ /* check size changes */ - if (peer->digest.cd && cblock.mask_size != peer->digest.cd->mask_size) { + if (pd->cd && cblock.mask_size != pd->cd->mask_size) { debug(72, 2) ("%s digest changed size: %d -> %d\n", - peer->host, cblock.mask_size, peer->digest.cd->mask_size); - freed_size = peer->digest.cd->mask_size; - cacheDigestDestroy(peer->digest.cd); - peer->digest.cd = NULL; + host, cblock.mask_size, pd->cd->mask_size); + freed_size = pd->cd->mask_size; + cacheDigestDestroy(pd->cd); + pd->cd = NULL; } - if (!peer->digest.cd) { + if (!pd->cd) { debug(72, 2) ("creating %s digest; size: %d (%+d) bytes\n", - peer->host, cblock.mask_size, (int) (cblock.mask_size - freed_size)); - peer->digest.cd = cacheDigestCreate(cblock.capacity, cblock.bits_per_entry); + host, cblock.mask_size, (int) (cblock.mask_size - freed_size)); + pd->cd = cacheDigestCreate(cblock.capacity, cblock.bits_per_entry); if (cblock.mask_size >= freed_size) kb_incr(&Counter.cd.memory, cblock.mask_size - freed_size); } - assert(peer->digest.cd); + assert(pd->cd); /* these assignments leave us in an inconsistent state until we finish reading the digest */ - peer->digest.cd->count = cblock.count; - peer->digest.cd->del_count = cblock.del_count; + pd->cd->count = cblock.count; + pd->cd->del_count = cblock.del_count; return 1; } static int -peerDigestUseful(const peer * peer) +peerDigestUseful(const PeerDigest * pd) { /* TODO: we should calculate the prob of a false hit instead of bit util */ - const int bit_util = cacheDigestBitUtil(peer->digest.cd); - if (bit_util > 75) { + const int bit_util = cacheDigestBitUtil(pd->cd); + if (bit_util > 65) { debug(72, 0) ("Warning: %s peer digest has too many bits on (%d%%).\n", - peer->host, bit_util); + strBuf(pd->host), bit_util); return 0; } return 1; } +static int +saneDiff(time_t diff) +{ + return abs(diff) > squid_curtime / 2 ? 0 : diff; +} + +void +peerDigestStatsReport(const PeerDigest * pd, StoreEntry * e) +{ +#define f2s(flag) (pd->flags.flag ? "yes" : "no") +#define appendTime(tm) storeAppendPrintf(e, "%s\t %10d\t %+d\t %+d\n", \ + ""#tm, pd->times.tm, \ + saneDiff(pd->times.tm - squid_curtime), \ + saneDiff(pd->times.tm - pd->times.initialized)) + + const char *host = pd ? strBuf(pd->host) : NULL; + assert(pd); + + storeAppendPrintf(e, "\npeer digest from %s\n", host); + + cacheDigestGuessStatsReport(&pd->stats.guess, e, host); + + storeAppendPrintf(e, "\nevent\t timestamp\t secs from now\t secs from init\n"); + appendTime(initialized); + appendTime(needed); + appendTime(requested); + appendTime(received); + appendTime(next_check); + + storeAppendPrintf(e, "peer digest state:\n"); + storeAppendPrintf(e, "\tneeded: %3s, usable: %3s, requested: %3s\n", + f2s(needed), f2s(usable), f2s(requested)); + storeAppendPrintf(e, "\n\tlast retry delay: %d secs\n", + pd->times.retry_delay); + storeAppendPrintf(e, "\tlast request response time: %d secs\n", + pd->times.req_delay); + storeAppendPrintf(e, "\tlast request result: %s\n", + pd->req_result ? pd->req_result : "(none)"); + + storeAppendPrintf(e, "\npeer digest traffic:\n"); + storeAppendPrintf(e, "\trequests sent: %d, volume: %d KB\n", + pd->stats.sent.msgs, (int) pd->stats.sent.kbytes.kb); + storeAppendPrintf(e, "\treplies recv: %d, volume: %d KB\n", + pd->stats.recv.msgs, (int) pd->stats.recv.kbytes.kb); + + storeAppendPrintf(e, "\npeer digest structure:\n"); + if (pd->cd) + cacheDigestReport(pd->cd, host, e); + else + storeAppendPrintf(e, "\tno in-memory copy\n"); +} + #endif Index: squid/src/peer_select.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/peer_select.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/peer_select.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/peer_select.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: peer_select.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: peer_select.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 44 Peer Selection Algorithm * AUTHOR: Duane Wessels @@ -44,7 +44,6 @@ "DEFAULT_PARENT", "SINGLE_PARENT", "FIRST_UP_PARENT", - "NO_PARENT_DIRECT", "FIRST_PARENT_MISS", "CLOSEST_PARENT_MISS", "CLOSEST_PARENT", @@ -54,7 +53,6 @@ "ROUNDROBIN_PARENT", #if USE_CACHE_DIGESTS "CACHE_DIGEST_HIT", - "NO_CACHE_DIGEST_DIRECT", #endif #if USE_CARP "CARP", @@ -69,6 +67,7 @@ static char *DirectStr[] = { + "DIRECT_UNKNOWN", "DIRECT_NO", "DIRECT_MAYBE", "DIRECT_YES" @@ -76,7 +75,7 @@ static void peerSelectFoo(ps_state *); static void peerPingTimeout(void *data); -static void peerSelectCallbackFail(ps_state * psstate); +static void peerSelectCallback(ps_state * psstate); static IRCB peerHandlePingReply; static void peerSelectStateFree(ps_state * psstate); static void peerIcpParentMiss(peer *, icp_common_t *, ps_state *); @@ -85,6 +84,11 @@ static void peerHandleHtcpReply(peer *, peer_t, htcpReplyData *, void *); #endif static int peerCheckNetdbDirect(ps_state * psstate); +static void peerGetSomeNeighbor(ps_state *); +static void peerGetSomeNeighborReplies(ps_state *); +static void peerGetSomeDirect(ps_state *); +static void peerGetSomeParent(ps_state *); +static void peerAddFwdServer(FwdServer **, peer *, hier_code); static void peerSelectStateFree(ps_state * psstate) @@ -107,12 +111,10 @@ peerSelectIcpPing(request_t * request, int direct, StoreEntry * entry) { int n; - if (entry == NULL) - return 0; - debug(44, 3) ("peerSelectIcpPing: %s\n", storeUrl(entry)); - if (entry->ping_status != PING_NONE) - return 0; + assert(entry); + assert(entry->ping_status == PING_NONE); assert(direct != DIRECT_YES); + debug(44, 3) ("peerSelectIcpPing: %s\n", storeUrl(entry)); if (!request->flags.hierarchical && direct != DIRECT_NO) return 0; if (EBIT_TEST(entry->flags, KEY_PRIVATE) && !neighbors_do_private_keys) @@ -124,37 +126,10 @@ } -peer * -peerGetSomeParent(request_t * request, hier_code * code) -{ - peer *p; - debug(44, 3) ("peerGetSomeParent: %s %s\n", - RequestMethodStr[request->method], - request->host); - if ((p = getDefaultParent(request))) { - *code = DEFAULT_PARENT; - return p; - } - if ((p = getRoundRobinParent(request))) { - *code = ROUNDROBIN_PARENT; - return p; - } - if ((p = getFirstUpParent(request))) { - *code = FIRSTUP_PARENT; - return p; - } - if ((p = getAnyParent(request))) { - *code = ANY_OLD_PARENT; - return p; - } - return NULL; -} - void peerSelect(request_t * request, StoreEntry * entry, PSC * callback, - PSC * fail_callback, void *callback_data) { ps_state *psstate = xcalloc(1, sizeof(ps_state)); @@ -162,12 +137,12 @@ debug(44, 3) ("peerSelect: %s\n", storeUrl(entry)); else debug(44, 3) ("peerSelect: %s\n", RequestMethodStr[request->method]); - cbdataAdd(psstate, MEM_NONE); + cbdataAdd(psstate, cbdataXfree, 0); psstate->request = requestLink(request); psstate->entry = entry; psstate->callback = callback; - psstate->fail_callback = fail_callback; psstate->callback_data = callback_data; + psstate->direct = DIRECT_UNKNOWN; #if USE_CACHE_DIGESTS request->hier.peer_select_start = current_time; #endif @@ -198,9 +173,10 @@ } static void -peerSelectCallback(ps_state * psstate, peer * p) +peerSelectCallback(ps_state * psstate) { StoreEntry *entry = psstate->entry; + FwdServer *fs = psstate->servers; void *data = psstate->callback_data; if (entry) { debug(44, 3) ("peerSelectCallback: %s\n", storeUrl(entry)); @@ -208,27 +184,18 @@ eventDelete(peerPingTimeout, psstate); entry->ping_status = PING_DONE; } + if (fs == NULL) { + debug(44, 1) ("Failed to select source for '%s'\n", storeUrl(entry)); + debug(44, 1) (" always_direct = %d\n", psstate->always_direct); + debug(44, 1) (" never_direct = %d\n", psstate->never_direct); + debug(44, 1) (" timedout = %d\n", psstate->ping.timedout); + } psstate->ping.stop = current_time; - if (cbdataValid(data)) - psstate->callback(p, data); - cbdataUnlock(data); - peerSelectStateFree(psstate); -} - -static void -peerSelectCallbackFail(ps_state * psstate) -{ - request_t *request = psstate->request; - void *data = psstate->callback_data; - const char *url = psstate->entry ? storeUrl(psstate->entry) : urlCanonical(request); - if (psstate->entry) - psstate->entry->ping_status = PING_DONE; - debug(44, 1) ("Failed to select source for '%s'\n", url); - debug(44, 1) (" always_direct = %d\n", psstate->always_direct); - debug(44, 1) (" never_direct = %d\n", psstate->never_direct); - debug(44, 1) (" timedout = %d\n", psstate->ping.timedout); - if (cbdataValid(data)) - psstate->fail_callback(NULL, data); + psstate->request->hier.ping = psstate->ping; + if (cbdataValid(data)) { + psstate->servers = NULL; + psstate->callback(fs, data); + } cbdataUnlock(data); peerSelectStateFree(psstate); } @@ -257,146 +224,216 @@ } static void -peerSelectFoo(ps_state * psstate) +peerSelectFoo(ps_state * ps) { - peer *p; - hier_code code; - StoreEntry *entry = psstate->entry; - request_t *request = psstate->request; - int direct; + StoreEntry *entry = ps->entry; + request_t *request = ps->request; debug(44, 3) ("peerSelectFoo: '%s %s'\n", RequestMethodStr[request->method], request->host); - if (psstate->always_direct == 0 && Config.accessList.AlwaysDirect) { - psstate->acl_checklist = aclChecklistCreate( - Config.accessList.AlwaysDirect, - request, - request->client_addr, - NULL, /* user agent */ - NULL); /* ident */ - aclNBCheck(psstate->acl_checklist, - peerCheckAlwaysDirectDone, - psstate); - return; - } else if (psstate->always_direct > 0) { - direct = DIRECT_YES; - } else if (psstate->never_direct == 0 && Config.accessList.NeverDirect) { - psstate->acl_checklist = aclChecklistCreate( - Config.accessList.NeverDirect, - request, - request->client_addr, - NULL, /* user agent */ - NULL); /* ident */ - aclNBCheck(psstate->acl_checklist, - peerCheckNeverDirectDone, - psstate); - return; - } else if (psstate->never_direct > 0) { - direct = DIRECT_NO; - } else if (request->flags.loopdetect) { - direct = DIRECT_YES; - } else { - direct = DIRECT_MAYBE; - } - debug(44, 3) ("peerSelectFoo: direct = %s\n", DirectStr[direct]); - if (direct == DIRECT_YES) { - debug(44, 3) ("peerSelectFoo: DIRECT\n"); - hierarchyNote(&request->hier, DIRECT, &psstate->ping, request->host); - peerSelectCallback(psstate, NULL); - return; - } - if ((p = getSingleParent(request))) { - code = SINGLE_PARENT; - debug(44, 3) ("peerSelectFoo: %s/%s\n", hier_strings[code], p->host); - hierarchyNote(&request->hier, code, &psstate->ping, p->host); - peerSelectCallback(psstate, p); - return; - } - if (!request->flags.hierarchical && direct != DIRECT_NO) { - debug(44, 3) ("peerSelectFoo: DIRECT for non-hierarchical request\n"); - hierarchyNote(&request->hier, DIRECT, &psstate->ping, request->host); - peerSelectCallback(psstate, NULL); + if (ps->direct == DIRECT_UNKNOWN) { + if (ps->always_direct == 0 && Config.accessList.AlwaysDirect) { + ps->acl_checklist = aclChecklistCreate( + Config.accessList.AlwaysDirect, + request, + request->client_addr, + request->my_addr, + NULL, /* user agent */ + NULL); /* ident */ + aclNBCheck(ps->acl_checklist, + peerCheckAlwaysDirectDone, + ps); + return; + } else if (ps->always_direct > 0) { + ps->direct = DIRECT_YES; + } else if (ps->never_direct == 0 && Config.accessList.NeverDirect) { + ps->acl_checklist = aclChecklistCreate( + Config.accessList.NeverDirect, + request, + request->client_addr, + request->my_addr, + NULL, /* user agent */ + NULL); /* ident */ + aclNBCheck(ps->acl_checklist, + peerCheckNeverDirectDone, + ps); + return; + } else if (ps->never_direct > 0) { + ps->direct = DIRECT_NO; + } else if (request->flags.loopdetect) { + ps->direct = DIRECT_YES; + } else { + ps->direct = DIRECT_MAYBE; + } + debug(44, 3) ("peerSelectFoo: direct = %s\n", + DirectStr[ps->direct]); + } + if (entry == NULL) { + (void) 0; + } else if (entry->ping_status == PING_NONE) { + peerGetSomeNeighbor(ps); + if (entry->ping_status == PING_WAITING) + return; + } else if (entry->ping_status == PING_WAITING) { + peerGetSomeNeighborReplies(ps); + entry->ping_status = PING_DONE; + } + if (Config.onoff.prefer_direct) + peerGetSomeDirect(ps); + peerGetSomeParent(ps); + if (!Config.onoff.prefer_direct) + peerGetSomeDirect(ps); + peerSelectCallback(ps); +} + +/* + * peerGetSomeNeighbor + * + * Selects a neighbor (parent or sibling) based on one of the + * following methods: + * Cache Digests + * CARP + * Netdb RTT estimates + * ICP/HTCP queries + */ +static void +peerGetSomeNeighbor(ps_state * ps) +{ + StoreEntry *entry = ps->entry; + request_t *request = ps->request; + peer *p; + hier_code code = HIER_NONE; + assert(entry->ping_status == PING_NONE); + if (ps->direct == DIRECT_YES) { + entry->ping_status = PING_DONE; return; } #if USE_CACHE_DIGESTS - else if ((p = neighborsDigestSelect(request, entry))) { - debug(44, 2) ("peerSelect: Using Cache Digest\n"); - request->hier.alg = PEER_SA_DIGEST; + if ((p = neighborsDigestSelect(request, entry))) { code = CACHE_DIGEST_HIT; - debug(44, 2) ("peerSelect: %s/%s\n", hier_strings[code], p->host); - hierarchyNote(&request->hier, code, &psstate->ping, p->host); - peerSelectCallback(psstate, p); - return; - } + } else #endif #if USE_CARP - else if ((p = carpSelectParent(request))) { - hierarchyNote(&request->hier, CARP, &psstate->ping, p->host); - peerSelectCallback(psstate, p); - return; - } + if ((p = carpSelectParent(request))) { + code = CARP; + } else #endif - else if ((p = netdbClosestParent(request))) { - request->hier.alg = PEER_SA_NETDB; + if ((p = netdbClosestParent(request))) { code = CLOSEST_PARENT; - debug(44, 2) ("peerSelect: %s/%s\n", hier_strings[code], p->host); - hierarchyNote(&request->hier, code, &psstate->ping, p->host); - peerSelectCallback(psstate, p); - return; - } else if (peerSelectIcpPing(request, direct, entry)) { - assert(entry->ping_status == PING_NONE); - request->hier.alg = PEER_SA_ICP; + } else if (peerSelectIcpPing(request, ps->direct, entry)) { debug(44, 3) ("peerSelect: Doing ICP pings\n"); - psstate->ping.start = current_time; - psstate->ping.n_sent = neighborsUdpPing(request, + ps->ping.start = current_time; + ps->ping.n_sent = neighborsUdpPing(request, entry, peerHandlePingReply, - psstate, - &psstate->ping.n_replies_expected, - &psstate->ping.timeout); - if (psstate->ping.n_sent == 0) + ps, + &ps->ping.n_replies_expected, + &ps->ping.timeout); + if (ps->ping.n_sent == 0) debug(44, 0) ("WARNING: neighborsUdpPing returned 0\n"); - debug(44, 3) ("peerSelectFoo: %d ICP replies expected, RTT %d msec\n", - psstate->ping.n_replies_expected, psstate->ping.timeout); - if (psstate->ping.n_replies_expected > 0) { + debug(44, 3) ("peerSelect: %d ICP replies expected, RTT %d msec\n", + ps->ping.n_replies_expected, ps->ping.timeout); + if (ps->ping.n_replies_expected > 0) { entry->ping_status = PING_WAITING; eventAdd("peerPingTimeout", peerPingTimeout, - psstate, - 0.001 * psstate->ping.timeout, + ps, + 0.001 * ps->ping.timeout, 0); return; } } - debug(44, 3) ("peerSelectFoo: After peerSelectIcpPing.\n"); - if (peerCheckNetdbDirect(psstate)) { + if (code != HIER_NONE) { + assert(p); + debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host); + peerAddFwdServer(&ps->servers, p, code); + } + entry->ping_status = PING_DONE; +} + +/* + * peerGetSomeNeighborReplies + * + * Selects a neighbor (parent or sibling) based on ICP/HTCP replies. + */ +static void +peerGetSomeNeighborReplies(ps_state * ps) +{ + StoreEntry *entry = ps->entry; + request_t *request = ps->request; + peer *p = NULL; + hier_code code = HIER_NONE; + assert(entry->ping_status == PING_WAITING); + assert(ps->direct != DIRECT_YES); + if (peerCheckNetdbDirect(ps)) { code = CLOSEST_DIRECT; debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], request->host); - hierarchyNote(&request->hier, code, &psstate->ping, request->host); - peerSelectCallback(psstate, NULL); - } else if ((p = whichPeer(&psstate->closest_parent_miss))) { + peerAddFwdServer(&ps->servers, NULL, code); + return; + } + if ((p = ps->hit)) { + code = ps->hit_type == PEER_PARENT ? PARENT_HIT : SIBLING_HIT; + } else +#if ALLOW_SOURCE_PING + if ((p = ps->secho)) { + code = SOURCE_FASTEST; + } else +#endif + if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr) { + p = whichPeer(&ps->closest_parent_miss); code = CLOSEST_PARENT_MISS; - debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host); - hierarchyNote(&request->hier, code, &psstate->ping, p->host); - peerSelectCallback(psstate, p); - } else if ((p = whichPeer(&psstate->first_parent_miss))) { + } else if (ps->first_parent_miss.sin_addr.s_addr != any_addr.s_addr) { + p = whichPeer(&ps->first_parent_miss); code = FIRST_PARENT_MISS; + } + if (p && code != HIER_NONE) { debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host); - hierarchyNote(&request->hier, code, &psstate->ping, p->host); - peerSelectCallback(psstate, p); - } else if (direct != DIRECT_NO) { - code = DIRECT; - debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], request->host); - hierarchyNote(&request->hier, code, &psstate->ping, request->host); - peerSelectCallback(psstate, NULL); - } else if ((p = peerGetSomeParent(request, &code))) { + peerAddFwdServer(&ps->servers, p, code); + } +} + + +/* + * peerGetSomeDirect + * + * Simply adds a 'direct' entry to the FwdServers list if this + * request can be forwarded directly to the origin server + */ +static void +peerGetSomeDirect(ps_state * ps) +{ + if (ps->direct == DIRECT_NO) + return; + if (ps->request->protocol == PROTO_WAIS) + /* Its not really DIRECT, now is it? */ + peerAddFwdServer(&ps->servers, Config.Wais.peer, DIRECT); + else + peerAddFwdServer(&ps->servers, NULL, DIRECT); +} + +static void +peerGetSomeParent(ps_state * ps) +{ + peer *p; + request_t *request = ps->request; + hier_code code = HIER_NONE; + debug(44, 3) ("peerGetSomeParent: %s %s\n", + RequestMethodStr[request->method], + request->host); + if (ps->direct == DIRECT_YES) + return; + if ((p = getDefaultParent(request))) { + code = DEFAULT_PARENT; + } else if ((p = getRoundRobinParent(request))) { + code = ROUNDROBIN_PARENT; + } else if ((p = getFirstUpParent(request))) { + code = FIRSTUP_PARENT; + } else if ((p = getAnyParent(request))) { + code = ANY_OLD_PARENT; + } + if (code != HIER_NONE) { debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host); - hierarchyNote(&request->hier, code, &psstate->ping, p->host); - peerSelectCallback(psstate, p); - } else { - code = NO_DIRECT_FAIL; - hierarchyNote(&request->hier, code, &psstate->ping, NULL); - peerSelectCallbackFail(psstate); + peerAddFwdServer(&ps->servers, p, code); } } @@ -407,9 +444,9 @@ StoreEntry *entry = psstate->entry; if (entry) debug(44, 3) ("peerPingTimeout: '%s'\n", storeUrl(entry)); - entry->ping_status = PING_TIMEOUT; if (!cbdataValid(psstate->callback_data)) { /* request aborted */ + entry->ping_status = PING_DONE; cbdataUnlock(psstate->callback_data); peerSelectStateFree(psstate); return; @@ -461,7 +498,6 @@ { ps_state *psstate = data; icp_opcode op = header->opcode; - request_t *request = psstate->request; debug(44, 3) ("peerHandleIcpReply: %s %s\n", icp_opcode_str[op], storeUrl(psstate->entry)); @@ -476,20 +512,18 @@ if (type == PEER_PARENT) peerIcpParentMiss(p, header, psstate); } else if (op == ICP_HIT) { - hierarchyNote(&request->hier, - type == PEER_PARENT ? PARENT_HIT : SIBLING_HIT, - &psstate->ping, - p->host); - peerSelectCallback(psstate, p); - return; - } else if (op == ICP_SECHO) { - hierarchyNote(&request->hier, - SOURCE_FASTEST, - &psstate->ping, - request->host); - peerSelectCallback(psstate, NULL); + psstate->hit = p; + psstate->hit_type = type; + peerSelectFoo(psstate); + return; + } +#if ALLOW_SOURCE_PING + else if (op == ICP_SECHO) { + psstate->secho = p; + peerSelectFoo(psstate); return; } +#endif if (psstate->ping.n_recv < psstate->ping.n_replies_expected) return; peerSelectFoo(psstate); @@ -506,11 +540,9 @@ storeUrl(psstate->entry)); psstate->ping.n_recv++; if (htcp->hit) { - hierarchyNote(&request->hier, - type == PEER_PARENT ? PARENT_HIT : SIBLING_HIT, - &psstate->ping, - p->host); - peerSelectCallback(psstate, p); + psstate->hit = p; + psstate->hit_type = type; + peerSelectFoo(psstate); return; } if (type == PEER_PARENT) @@ -562,3 +594,18 @@ else debug(44, 1) ("peerHandlePingReply: unknown protocol_t %d\n", (int) proto); } + +static void +peerAddFwdServer(FwdServer ** FS, peer * p, hier_code code) +{ + FwdServer *fs = memAllocate(MEM_FWD_SERVER); + debug(44, 5) ("peerAddFwdServer: adding %s %s\n", + p ? p->host : "DIRECT", + hier_strings[code]); + fs->peer = p; + fs->code = code; + cbdataLock(fs->peer); + while (*FS) + FS = &(*FS)->next; + *FS = fs; +} Index: squid/src/pinger.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/pinger.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/pinger.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/pinger.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: pinger.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: pinger.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 42 ICMP Pinger program * AUTHOR: Duane Wessels @@ -152,6 +152,14 @@ struct sockaddr_in S; memset(pkt, '\0', MAX_PKT_SZ); icmp = (struct icmphdr *) (void *) pkt; + + /* + * cevans - beware signed/unsigned issues in untrusted data from + * the network!! + */ + if (len < 0) { + len = 0; + } icmp->icmp_type = ICMP_ECHO; icmp->icmp_code = 0; icmp->icmp_cksum = 0; @@ -169,6 +177,9 @@ } icmp->icmp_cksum = in_cksum((u_short *) icmp, icmp_pktsize); S.sin_family = AF_INET; + /* + * cevans: alert: trusting to-host, was supplied in network packet + */ S.sin_addr = to; S.sin_port = 0; assert(icmp_pktsize <= MAX_PKT_SZ); @@ -294,9 +305,12 @@ if (n < 0) return n; guess_size = n - (sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ); - if (guess_size != pecho.psize) + if (guess_size != pecho.psize) { fprintf(stderr, "size mismatch, guess=%d psize=%d\n", guess_size, pecho.psize); + errno = 0; + return -1; + } pingerSendEcho(pecho.to, pecho.opcode, pecho.payload, @@ -336,12 +350,19 @@ char *t; time_t last_check_time = 0; +/* + * cevans - do this first. It grabs a raw socket. After this we can + * drop privs + */ + pingerOpen(); + setgid(getgid()); + setuid(getuid()); + if ((t = getenv("SQUID_DEBUG"))) debug_args = xstrdup(t); getCurrentTime(); _db_init(NULL, debug_args); - pingerOpen(); for (;;) { tv.tv_sec = 10; tv.tv_usec = 0; Index: squid/src/protos.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/protos.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/protos.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/protos.h 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: protos.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -36,7 +36,7 @@ extern void accessLogClose(void); extern void accessLogInit(void); extern const char *accessLogTime(time_t); -extern void hierarchyNote(HierarchyLogEntry *, hier_code, ping_data *, const char *); +extern void hierarchyNote(HierarchyLogEntry *, hier_code, const char *); #if FORW_VIA_DB extern void fvdbCountVia(const char *key); extern void fvdbCountForw(const char *key); @@ -45,6 +45,7 @@ extern aclCheck_t *aclChecklistCreate(const struct _acl_access *, request_t *, struct in_addr src, + struct in_addr me, const char *user_agent, const char *ident); extern void aclNBCheck(aclCheck_t *, PF *, void *); @@ -55,7 +56,7 @@ extern void aclDestroyAcls(acl **); extern void aclParseAccessLine(struct _acl_access **); extern void aclParseAclLine(acl **); -extern struct _acl *aclFindByName(const char *name); +extern int aclIsProxyAuth(const char *name); extern int aclGetDenyInfoPage(acl_deny_info_list ** head, const char *name); extern void aclParseDenyInfoLine(struct _acl_deny_info_list **); extern void aclDestroyDenyInfoList(struct _acl_deny_info_list **); @@ -75,6 +76,7 @@ extern int aio_unlink(const char *, aio_result_t *); extern int aio_opendir(const char *, aio_result_t *); extern aio_result_t *aio_poll_done(void); +extern int aio_operations_pending(void); extern void aioCancel(int, void *); extern void aioOpen(const char *, int, mode_t, AIOCB *, void *, void *); @@ -84,27 +86,29 @@ extern void aioStat(char *, struct stat *, AIOCB *, void *, void *); extern void aioUnlink(const char *, AIOCB *, void *); extern void aioCheckCallbacks(void); +extern void aioSync(void); #endif extern int parseConfigFile(const char *file_name); extern void intlistDestroy(intlist **); extern int intlistFind(intlist * list, int i); extern wordlist *wordlistAdd(wordlist **, const char *); +extern wordlist *wordlistDup(const wordlist *); extern void wordlistDestroy(wordlist **); extern void configFreeMemory(void); extern void wordlistCat(const wordlist *, MemBuf * mb); extern void cbdataInit(void); #if CBDATA_DEBUG -extern void cbdataAddDbg(const void *p, mem_type, const char *, int); +extern void cbdataAddDbg(const void *p, CBDUNL *, int, const char *, int); #else -extern void cbdataAdd(const void *p, mem_type); +extern void cbdataAdd(const void *p, CBDUNL *, int); #endif extern void cbdataFree(void *p); extern void cbdataLock(const void *p); extern void cbdataUnlock(const void *p); extern int cbdataValid(const void *p); -extern void cbdataDump(StoreEntry *); +extern CBDUNL cbdataXfree; extern void clientdbInit(void); extern void clientdbUpdate(struct in_addr, log_type, protocol_t, size_t); @@ -171,7 +175,7 @@ extern void packerToMemInit(Packer * p, MemBuf * mb); extern void packerClean(Packer * p); extern void packerAppend(Packer * p, const char *buf, int size); -#ifdef __STDC__ +#if STDC_HEADERS extern void packerPrintf(Packer * p, const char *fmt,...); #else extern void packerPrintf(); @@ -185,11 +189,12 @@ extern void _db_init(const char *logfile, const char *options); extern void _db_rotate_log(void); -#ifdef __STDC__ +#if STDC_HEADERS extern void _db_print(const char *,...); #else extern void _db_print(); #endif +extern void xassert(const char *, const char *, int); /* packs, then prints an object using debug() */ extern void debugObj(int section, int level, const char *label, void *obj, ObjPackMethod pm); @@ -213,9 +218,13 @@ extern time_t eventNextTime(void); extern void eventDelete(EVH * func, void *arg); extern void eventInit(void); +extern void eventFreeMemory(void); extern int eventFind(EVH *, void *); extern void fd_close(int fd); +#if USE_ASYNC_IO +extern void fd_was_closed(int fd); +#endif extern void fd_open(int fd, unsigned int type, const char *); extern void fd_note(int fd, const char *); extern void fd_bytes(int fd, int len, unsigned int type); @@ -245,17 +254,17 @@ extern void fqdncache_restart(void); extern EVH fqdncache_purgelru; -extern void ftpStart(request_t * req, StoreEntry * entry, int); +extern void ftpStart(FwdState *); extern char *ftpUrlWith2f(const request_t *); -extern void gopherStart(StoreEntry *, int fd); +extern void gopherStart(FwdState *); extern int gopherCachable(const char *); -extern void whoisStart(FwdState *, int fd); +extern void whoisStart(FwdState *); extern int httpCachable(method_t); -extern void httpStart(FwdState *, int fd); +extern void httpStart(FwdState *); extern void httpParseReplyHeaders(const char *, http_reply *); extern void httpProcessReplyHeader(HttpStateData *, const char *, int); extern size_t httpBuildRequestPrefix(request_t * request, @@ -330,6 +339,7 @@ extern int httpHdrRangeIsComplex(const HttpHdrRange * range); extern int httpHdrRangeWillBeComplex(const HttpHdrRange * range); extern size_t httpHdrRangeFirstOffset(const HttpHdrRange * range); +extern size_t httpHdrRangeLowestOffset(const HttpHdrRange * range, size_t size); /* Http Content Range Header Field */ @@ -347,7 +357,8 @@ extern HttpHeaderFieldInfo *httpHeaderBuildFieldsInfo(const HttpHeaderFieldAttrs * attrs, int count); extern void httpHeaderDestroyFieldsInfo(HttpHeaderFieldInfo * info, int count); extern int httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * attrs, int end); -extern void httpHeaderMaskInit(HttpHeaderMask * mask); +extern int httpHeaderIdByNameDef(const char *name, int name_len); +extern void httpHeaderMaskInit(HttpHeaderMask * mask, int value); extern void httpHeaderCalcMask(HttpHeaderMask * mask, const int *enums, int count); extern int httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive); extern void httpHeaderAddContRange(HttpHeader * hdr, HttpHdrRangeSpec spec, size_t ent_len); @@ -359,7 +370,7 @@ extern int httpHeaderParseInt(const char *start, int *val); extern int httpHeaderParseSize(const char *start, size_t * sz); extern int httpHeaderReset(HttpHeader * hdr); -#ifdef __STDC__ +#if STDC_HEADERS extern void httpHeaderPutStrf(HttpHeader * hdr, http_hdr_type id, const char *fmt,...); #else extern void @@ -480,15 +491,24 @@ #ifdef SQUID_SNMP extern PF snmpHandleUdp; extern void snmpInit(void); -extern int snmpInitConfig(void); extern void snmpConnectionOpen(void); extern void snmpConnectionShutdown(void); extern void snmpConnectionClose(void); -extern int snmpCreateView(char **); -extern int snmpCreateUser(char **); -extern int snmpCreateCommunity(char **); -extern void snmpTokenize(char *, char **, int); -extern int snmpCompare(oid * name1, int len1, oid * name2, int len2); +extern void snmpDebugOid(int lvl, oid * Name, snint Len); +extern void addr2oid(struct in_addr addr, oid * Dest); +extern struct in_addr *oid2addr(oid * id); +extern struct in_addr *client_entry(struct in_addr *current); +extern variable_list *snmp_basicFn(variable_list *, snint *); +extern variable_list *snmp_confFn(variable_list *, snint *); +extern variable_list *snmp_sysFn(variable_list *, snint *); +extern variable_list *snmp_prfSysFn(variable_list *, snint *); +extern variable_list *snmp_prfProtoFn(variable_list *, snint *); +extern variable_list *snmp_prfPeerFn(variable_list *, snint *); +extern variable_list *snmp_netIpFn(variable_list *, snint *); +extern variable_list *snmp_netFqdnFn(variable_list *, snint *); +extern variable_list *snmp_netDnsFn(variable_list *, snint *); +extern variable_list *snmp_meshPtblFn(variable_list *, snint *); +extern variable_list *snmp_meshCtblFn(variable_list *, snint *); #endif /* SQUID_SNMP */ extern void icpHandleIcpV3(int, struct sockaddr_in, char *, int); @@ -531,7 +551,7 @@ /* calls memcpy, appends exactly size bytes, extends buffer if needed */ extern void memBufAppend(MemBuf * mb, const char *buf, mb_size_t size); /* calls snprintf, extends buffer if needed */ -#ifdef __STDC__ +#if STDC_HEADERS extern void memBufPrintf(MemBuf * mb, const char *fmt,...); #else extern void memBufPrintf(); @@ -581,14 +601,16 @@ extern void neighborAdd(const char *, const char *, int, int, int, int, int); extern void neighbors_open(int); extern peer *peerFindByName(const char *); +extern peer *peerFindByNameAndPort(const char *, unsigned short); extern peer *getDefaultParent(request_t * request); extern peer *getRoundRobinParent(request_t * request); extern peer *getAnyParent(request_t * request); extern lookup_t peerDigestLookup(peer * p, request_t * request, StoreEntry * entry); extern peer *neighborsDigestSelect(request_t * request, StoreEntry * entry); extern void peerNoteDigestLookup(request_t * request, peer * p, lookup_t lookup); +extern void peerNoteDigestGone(peer * p); extern int neighborUp(const peer * e); -extern void peerDestroy(peer * e); +extern CBDUNL peerDestroy; extern char *neighborTypeStr(const peer * e); extern peer_t neighborType(const peer *, const request_t *); extern void peerCheckConnectStart(peer *); @@ -622,19 +644,24 @@ extern void cachemgrRegister(const char *, const char *, OBJH *, int, int); extern void cachemgrInit(void); -extern void peerSelect(request_t *, StoreEntry *, PSC *, PSC *, void *data); -extern peer *peerGetSomeParent(request_t *, hier_code *); +extern void peerSelect(request_t *, StoreEntry *, PSC *, void *data); extern void peerSelectInit(void); /* peer_digest.c */ -extern EVH peerDigestInit; +extern PeerDigest *peerDigestCreate(peer * p); +extern void peerDigestNeeded(PeerDigest * pd); +extern void peerDigestNotePeerGone(PeerDigest * pd); +extern void peerDigestStatsReport(const PeerDigest * pd, StoreEntry * e); /* forward.c */ -extern void fwdStart(int, StoreEntry *, request_t *, struct in_addr); +extern void fwdStart(int, StoreEntry *, request_t *, struct in_addr, struct in_addr); extern DEFER fwdCheckDeferRead; -extern void fwdFail(FwdState *, int, http_status, int); -extern STABH fwdAbort; +extern void fwdFail(FwdState *, ErrorState *); extern void fwdUnregister(int fd, FwdState *); +extern void fwdComplete(FwdState * fwdState); +extern void fwdInit(void); +extern int fwdReforwardableStatus(http_status s); +extern void fwdServersFree(FwdServer ** FS); extern void urnStart(request_t *, StoreEntry *); @@ -647,6 +674,7 @@ extern void authenticateShutdown(void); extern void refreshAddToList(const char *, int, time_t, int, time_t); +extern int refreshIsCachable(const StoreEntry *); extern int refreshCheckHTTP(const StoreEntry *, request_t *); extern int refreshCheckICP(const StoreEntry *, request_t *); extern int refreshCheckDigest(const StoreEntry *, time_t delta); @@ -659,9 +687,13 @@ extern void start_announce(void *unused); extern void sslStart(int fd, const char *, request_t *, size_t * sz); -extern void waisStart(request_t *, StoreEntry *, int fd); -extern void passStart(int, const char *, request_t *, size_t *); -extern void identStart(int, ConnStateData *, IDCB * callback, void *); +extern void waisStart(FwdState *); + +/* ident.c */ +#if USE_IDENT +extern void identStart(struct sockaddr_in *me, struct sockaddr_in *peer, IDCB * callback, void *cbdata); +extern void identInit(void); +#endif extern void statInit(void); extern void statFreeMemory(void); @@ -670,6 +702,9 @@ extern int stat5minClientRequests(void); extern double stat5minCPUUsage(void); extern const char *storeEntryFlags(const StoreEntry *); +extern double statRequestHitRatio(int minutes); +extern double statByteHitRatio(int minutes); + /* StatHist */ @@ -702,7 +737,7 @@ extern void memConfigure(); extern void *memAllocate(mem_type); extern void *memAllocBuf(size_t net_size, size_t * gross_size); -extern void memFree(mem_type, void *); +extern CBDUNL memFree; extern void memFreeBuf(size_t size, void *); extern void memFree2K(void *); extern void memFree4K(void *); @@ -742,12 +777,9 @@ extern StoreEntry *storeCreateEntry(const char *, const char *, request_flags, method_t); extern void storeSetPublicKey(StoreEntry *); extern void storeComplete(StoreEntry *); -#ifdef PPNR_WIP -extern void storePPNR(StoreEntry *); -#endif /* PPNR_WIP */ extern void storeInit(void); extern int storeClientWaiting(const StoreEntry *); -extern void storeAbort(StoreEntry *, int); +extern void storeAbort(StoreEntry *); extern void storeAppend(StoreEntry *, const char *, int); extern void storeLockObject(StoreEntry *); extern void storeSwapInStart(StoreEntry *, SIH *, void *data); @@ -786,7 +818,7 @@ extern void storeBufferFlush(StoreEntry *); extern void storeHashInsert(StoreEntry * e, const cache_key *); extern void storeSetMemStatus(StoreEntry * e, int); -#ifdef __STDC__ +#if STDC_HEADERS extern void storeAppendPrintf(StoreEntry *, const char *,...); #else extern void storeAppendPrintf(); @@ -799,6 +831,7 @@ extern int contentLen(const StoreEntry * e); extern HttpReply *storeEntryReply(StoreEntry *); extern int storeTooManyDiskFilesOpen(void); +extern void storeEntryReset(StoreEntry *); /* * store_log.c @@ -818,7 +851,6 @@ extern const cache_key *storeKeyScan(const char *); extern const char *storeKeyText(const cache_key *); extern const cache_key *storeKeyPublic(const char *, const method_t); -extern const cache_key *storeKeyPublicOld(const char *, const method_t); extern const cache_key *storeKeyPrivate(const char *, method_t, int); extern int storeKeyHashBuckets(int); extern int storeKeyNull(const cache_key *); @@ -895,8 +927,6 @@ /* * store_swapout.c */ -extern void storeSwapOutStart(StoreEntry * e); -extern void storeSwapOutHandle(int fdnotused, int flag, size_t len, void *data); extern void storeCheckSwapOut(StoreEntry * e); extern void storeSwapOutFileClose(StoreEntry * e); extern int storeSwapOutWriteQueued(MemObject * mem); @@ -920,7 +950,7 @@ extern void safeunlink(const char *path, int quiet); extern void death(int sig); extern void fatal(const char *message); -#ifdef __STDC__ +#if STDC_HEADERS extern void fatalf(const char *fmt,...); #else extern void fatalf(); @@ -954,7 +984,7 @@ extern void dumpMallocStats(void); extern void pumpInit(int fd, request_t * r, char *uri); -extern void pumpStart(int, StoreEntry *, request_t *, CWCB * callback, void *); +extern void pumpStart(int, FwdState *, CWCB * callback, void *); extern int pumpMethod(method_t method); extern int pumpRestart(request_t *); @@ -1076,14 +1106,25 @@ #endif #if DELAY_POOLS -extern int delayClient(clientHttpRequest *); extern void delayPoolsInit(void); +extern void delayInitDelayData(unsigned short pools); +extern void delayFreeDelayData(); +extern void delayCreateDelayPool(unsigned short pool, u_char class); +extern void delayInitDelayPool(unsigned short pool, u_char class, delaySpecSet * rates); +extern void delayFreeDelayPool(unsigned short pool); +extern void delayPoolsReconfigure(); +extern void delaySetNoDelay(int fd); +extern void delayClearNoDelay(int fd); +extern int delayIsNoDelay(int fd); +extern delay_id delayClient(request_t *); extern EVH delayPoolsUpdate; -extern int delayMostBytesWanted(const MemObject * mem, int max); -extern int delayMostBytesAllowed(const MemObject * mem); +extern int delayBytesWanted(delay_id d, int min, int max); extern void delayBytesIn(delay_id, int qty); +extern int delayMostBytesWanted(const MemObject * mem, int max); +extern delay_id delayMostBytesAllowed(const MemObject * mem); extern void delaySetStoreClient(StoreEntry * e, void *data, delay_id delay_id); -extern int delayBytesWanted(delay_id d, int min, int max); +void delayRegisterDelayIdPtr(delay_id * loc); +void delayUnregisterDelayIdPtr(delay_id * loc); #endif /* helper.c */ @@ -1094,6 +1135,13 @@ extern helper *helperCreate(const char *); extern void helperFree(helper *); +#if USE_LEAKFINDER +extern void leakInit(void); +extern void *leakAddFL(void *, const char *, int); +extern void *leakTouchFL(void *, const char *, int); +extern void *leakFree(void *); +#endif + /* * prototypes for system functions missing from system includes */ Index: squid/src/pump.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/pump.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/pump.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/pump.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: pump.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: pump.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 61 PUMP handler * AUTHOR: Kostas Anagnostakis @@ -37,6 +37,7 @@ #define PUMP_MAXBUFFER 2*SQUID_UDP_SO_SNDBUF struct _PumpStateData { + FwdState *fwd; request_t *req; int c_fd; /* client fd */ int s_fd; /* server end */ @@ -93,7 +94,7 @@ p->request_entry = storeCreateEntry(new_key, new_key, flags, r->method); storeClientListAdd(p->request_entry, p); #if DELAY_POOLS - delaySetStoreClient(p->request_entry, p, r->delay_id); + delaySetStoreClient(p->request_entry, p, delayClient(r)); #endif /* * initialize data structure @@ -106,19 +107,20 @@ p->cbdata = NULL; p->next = pump_head; pump_head = p; - cbdataAdd(p, MEM_NONE); + cbdataAdd(p, cbdataXfree, 0); comm_add_close_handler(p->c_fd, pumpFree, p); commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); debug(61, 4) ("pumpInit: FD %d, Created %p\n", fd, p); } void -pumpStart(int s_fd, StoreEntry * reply_entry, request_t * r, CWCB * callback, void *cbdata) +pumpStart(int s_fd, FwdState * fwd, CWCB * callback, void *cbdata) { PumpStateData *p = NULL; + request_t *r = fwd->request; size_t copy_sz; debug(61, 3) ("pumpStart: FD %d, key %s\n", - s_fd, storeKeyText(reply_entry->key)); + s_fd, storeKeyText(fwd->entry->key)); /* * find state data generated by pumpInit in linked list */ @@ -126,11 +128,13 @@ assert(p != NULL); assert(p->request_entry); assert(p->c_fd > -1); + assert(r == p->req); /* * fill in the rest of data needed by the pump */ + p->fwd = fwd; p->s_fd = s_fd; - p->reply_entry = reply_entry; + p->reply_entry = fwd->entry; p->callback = callback; p->cbdata = cbdata; cbdataLock(p->cbdata); @@ -142,12 +146,8 @@ if (p->rcvd < p->cont_len && r->body_sz > 0) { assert(p->request_entry->store_status == STORE_PENDING); assert(r->body != NULL); - if (r->flags.proxy_keepalive) { - assert(r->body_sz <= p->cont_len); - copy_sz = XMIN(r->body_sz, p->cont_len); - } else { - copy_sz = r->body_sz; - } + assert(r->body_sz <= p->cont_len); + copy_sz = XMIN(r->body_sz, p->cont_len); debug(61, 3) ("pumpStart: Appending %d bytes from r->body\n", copy_sz); storeAppend(p->request_entry, r->body, copy_sz); p->rcvd = copy_sz; @@ -162,7 +162,7 @@ commSetDefer(p->c_fd, pumpReadDefer, p); } p->sent = 0; - if (r->flags.proxy_keepalive && p->sent == p->cont_len) { + if (p->sent == p->cont_len) { pumpServerCopyComplete(p->s_fd, NULL, 0, DISK_OK, p); } else { storeClientCopy(p->request_entry, p->sent, p->sent, 4096, @@ -178,13 +178,13 @@ debug(61, 5) ("pumpServerCopy: called with size=%d\n", size); if (size < 0) { debug(61, 5) ("pumpServerCopy: freeing and returning\n"); - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); return; } if (size == 0) { debug(61, 5) ("pumpServerCopy: done, finishing\n", size); pumpServerCopyComplete(p->s_fd, NULL, 0, DISK_OK, p); - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); return; } debug(61, 5) ("pumpServerCopy: to FD %d, %d bytes\n", p->s_fd, size); @@ -205,14 +205,13 @@ pumpClose(p); return; } - if (p->request_entry->store_status == STORE_ABORTED) { - debug(61, 5) ("pumpServerCopyComplete: STORE_ABORTED\n"); + if (EBIT_TEST(p->request_entry->flags, ENTRY_ABORTED)) { + debug(61, 5) ("pumpServerCopyComplete: ENTRY_ABORTED\n"); pumpClose(p); return; } p->sent += size; - if (p->req->flags.proxy_keepalive) - assert(p->sent <= p->cont_len); + assert(p->sent <= p->cont_len); if (p->sent < p->cont_len) { storeClientCopy(p->request_entry, p->sent, p->sent, 4096, memAllocate(MEM_4K_BUF), @@ -240,11 +239,9 @@ PumpStateData *p = data; StoreEntry *req = p->request_entry; LOCAL_ARRAY(char, buf, SQUID_TCP_SO_RCVBUF); - int bytes_to_read = SQUID_TCP_SO_RCVBUF; + int bytes_to_read = XMIN(p->cont_len - p->rcvd, SQUID_TCP_SO_RCVBUF); int len = 0; errno = 0; - if (p->cont_len - p->rcvd < bytes_to_read) - bytes_to_read = p->cont_len - p->rcvd; Counter.syscalls.sock.reads++; len = read(fd, buf, bytes_to_read); fd_bytes(fd, len, FD_READ); @@ -278,7 +275,7 @@ } if (len > 0) { int delta = p->rcvd + len - p->cont_len; - if (delta > 0) { + if (delta > 0 && p->req->flags.proxy_keepalive) { debug(61, delta == 2 ? 3 : 1) ("pumpReadFromClient: Warning: read %d bytes past content-length, truncating\n", delta); len = p->cont_len - p->rcvd; } @@ -292,10 +289,12 @@ return; } /* all done! */ - assert(p->rcvd == p->cont_len); + if (p->req->flags.proxy_keepalive) + assert(p->rcvd == p->cont_len); debug(61, 2) ("pumpReadFromClient: finished!\n"); storeComplete(req); commSetDefer(p->c_fd, NULL, NULL); + commSetTimeout(p->c_fd, -1, NULL, NULL); } static int @@ -324,15 +323,10 @@ p->flags.closing = 1; if (req != NULL && req->store_status == STORE_PENDING) { storeUnregister(req, p); - storeAbort(req, 0); } if (rep != NULL && rep->store_status == STORE_PENDING) { - /* - * Set the storeAbort() 'cbflag' so that the server-side - * abort handler (httpAbort) gets called and the server-side - * FD gets closed. - */ - storeAbort(rep, 1); + ErrorState *err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR); + fwdFail(p->fwd, err); } if (p->s_fd > -1) { comm_close(p->s_fd); @@ -369,25 +363,17 @@ rep = p->reply_entry; if (req != NULL) { storeUnregister(req, p); - if (req->store_status == STORE_PENDING) - storeAbort(req, 0); storeUnlockObject(req); p->request_entry = NULL; } if (rep != NULL) { - /* - * Set the storeAbort() 'cbflag' so that the server-side - * abort handler (httpAbort) gets called and the server-side - * FD gets closed. - */ - if (rep->store_status == STORE_PENDING) - storeAbort(rep, 1); + debug(61, 3) ("pumpFree: did the server-side FD (%d) get closed?\n", p->s_fd); storeUnlockObject(rep); p->reply_entry = NULL; } requestUnlink(p->req); if (p->s_fd > -1) { - assert(0 == fd_table[p->s_fd].open); + assert(!fd_table[p->s_fd].flags.open); p->s_fd = -1; } cbdataFree(p); Index: squid/src/redirect.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/redirect.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/redirect.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/redirect.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: redirect.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: redirect.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 29 Redirector * AUTHOR: Duane Wessels @@ -100,13 +100,13 @@ return; } r = xcalloc(1, sizeof(redirectStateData)); - cbdataAdd(r, MEM_NONE); + cbdataAdd(r, cbdataXfree, 0); r->orig_url = xstrdup(http->uri); r->client_addr = conn->log_addr; - if (conn->ident.ident == NULL || *conn->ident.ident == '\0') { + if (conn->ident == NULL || *conn->ident == '\0') { r->client_ident = dash_str; } else { - r->client_ident = conn->ident.ident; + r->client_ident = conn->ident; } r->method_s = RequestMethodStr[http->request->method]; r->handler = handler; Index: squid/src/refresh.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/refresh.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/refresh.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/refresh.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,7 +1,7 @@ /* - * $Id: refresh.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: refresh.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 22 Refresh Calculation * AUTHOR: Harvest Derived @@ -41,7 +41,7 @@ #include "squid.h" typedef enum { - rcHTTP, rcICP, rcCDigest, rcCount + rcHTTP, rcICP, rcCDigest, rcStore, rcCount } refreshCountsEnum; static struct RefreshCounts { @@ -187,8 +187,8 @@ rc->negative_age_stale++; return 1; } - if (request->max_age > -1) { - if (age > request->max_age) { + if (request->cache_control && request->cache_control->max_age > -1) { + if (age > request->cache_control->max_age) { debug(22, 3) ("refreshCheck: YES: age > client-max-age\n"); rc->request_max_age_stale++; return 1; @@ -255,6 +255,34 @@ return 1; } +int +refreshIsCachable(const StoreEntry * entry) +{ + /* + * Don't look at the request to avoid no-cache and other nuisances. + * the object should have a mem_obj so the URL will be found there. + * 60 seconds delta, to avoid objects which expire almost + * immediately, and which can't be refreshed. + */ + if (!refreshCheck(entry, NULL, 60, &refreshCounts[rcStore])) + /* Does not need refresh. This is certainly cachable */ + return 1; + if (entry->lastmod < 0) + /* Last modified is needed to do a refresh */ + return 0; + if (entry->mem_obj == NULL) + /* no mem_obj? */ + return 1; + if (entry->mem_obj->reply) + /* no reply? */ + return 1; + if (entry->mem_obj->reply->content_length == 0) + /* No use refreshing (caching?) 0 byte objects */ + return 0; + /* This seems to be refreshable. Cache it */ + return 1; +} + /* refreshCheck... functions below are protocol-specific wrappers around * refreshCheck() function above */ @@ -357,6 +385,7 @@ memset(refreshCounts, 0, sizeof(refreshCounts)); refreshCounts[rcHTTP].proto = "HTTP"; refreshCounts[rcICP].proto = "ICP"; + refreshCounts[rcStore].proto = "On Store"; refreshCounts[rcCDigest].proto = "Cache Digests"; cachemgrRegister("refresh", Index: squid/src/send-announce.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/send-announce.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/send-announce.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/send-announce.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: send-announce.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: send-announce.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 27 Cache Announcer * AUTHOR: Duane Wessels @@ -45,7 +45,7 @@ return; if (theOutIcpConnection < 0) return; - cbdataAdd(junk = xmalloc(1), MEM_NONE); + cbdataAdd(junk = xmalloc(1), cbdataXfree, 0); ipcache_nbgethostbyname(Config.Announce.host, send_announce, junk); eventAdd("send_announce", start_announce, NULL, (double) Config.Announce.period, 1); } Index: squid/src/snmp_agent.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/snmp_agent.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/snmp_agent.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/snmp_agent.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: snmp_agent.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: snmp_agent.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 49 SNMP Interface * AUTHOR: Kostas Anagnostakis @@ -35,18 +35,10 @@ #include "squid.h" - -#include "snmp.h" -#include "snmp_impl.h" -#include "asn1.h" -#include "snmp_api.h" -#include "snmp_vars.h" -#include "snmp_oidlist.h" #include "cache_snmp.h" extern StatCounters *snmpStatGet(int); - /************************************************************************ SQUID MIB Implementation @@ -69,7 +61,7 @@ Answer->val_len = sizeof(snint); Answer->val.integer = xmalloc(Answer->val_len); Answer->type = ASN_INTEGER; - *(Answer->val.integer) = store_mem_size; + *(Answer->val.integer) = store_mem_size >> 10; break; case SYSSTOR: Answer->val_len = sizeof(snint); @@ -125,25 +117,13 @@ Answer->val_len = sizeof(snint); Answer->val.integer = xmalloc(Answer->val_len); Answer->type = ASN_INTEGER; - *(Answer->val.integer) = (snint) Config.Mem.maxSize; - break; - case CONF_ST_MHIWM: - Answer->val_len = sizeof(snint); - Answer->val.integer = xmalloc(Answer->val_len); - Answer->type = ASN_INTEGER; - *(Answer->val.integer) = (snint) Config.Mem.highWaterMark; - break; - case CONF_ST_MLOWM: - Answer->val_len = sizeof(snint); - Answer->val.integer = xmalloc(Answer->val_len); - Answer->type = ASN_INTEGER; - *(Answer->val.integer) = (snint) Config.Mem.lowWaterMark; + *(Answer->val.integer) = (snint) Config.memMaxSize >> 20; break; case CONF_ST_SWMAXSZ: Answer->val_len = sizeof(snint); Answer->val.integer = xmalloc(Answer->val_len); Answer->type = ASN_INTEGER; - *(Answer->val.integer) = (snint) Config.Swap.maxSize; + *(Answer->val.integer) = (snint) Config.Swap.maxSize >> 10; break; case CONF_ST_SWHIWM: Answer->val_len = sizeof(snint); @@ -197,13 +177,6 @@ if (p->in_addr.sin_addr.s_addr == laddr->s_addr) break; -#if SNMP_OLD_INDEX - p = Config.peers; - cnt = Var->name[LEN_SQ_MESH + 3]; - debug(49, 5) ("snmp_meshPtblFn: we want .x.%d\n", Var->name[10]); - while (--cnt) - if (!(p = p->next)); -#endif if (p == NULL) { *ErrP = SNMP_ERR_NOSUCHNAME; snmp_var_free(Answer); @@ -321,17 +294,18 @@ *(Answer->val.integer) = IOStats.Http.reads; Answer->type = SMI_COUNTER32; break; - case PERF_SYS_DEFR: /* XXX unused, remove me */ - Answer->type = SMI_COUNTER32; - *(Answer->val.integer) = 0; - break; case PERF_SYS_MEMUSAGE: *(Answer->val.integer) = (snint) memTotalAllocated() >> 10; break; - case PERF_SYS_CPUUSAGE: + case PERF_SYS_CPUTIME: squid_getrusage(&rusage); *(Answer->val.integer) = (snint) rusage_cputime(&rusage); break; + case PERF_SYS_CPUUSAGE: + squid_getrusage(&rusage); + *(Answer->val.integer) = (snint) + dpercent(rusage_cputime(&rusage), tvSubDsec(squid_start, current_time)); + break; case PERF_SYS_MAXRESSZ: squid_getrusage(&rusage); *(Answer->val.integer) = (snint) rusage_maxrss(&rusage); @@ -428,6 +402,9 @@ case PERF_PROTOSTAT_AGGR_CURSWAP: *(Answer->val.integer) = (snint) store_swap_size; break; + case PERF_PROTOSTAT_AGGR_CLIENTS: + *(Answer->val.integer) = (snint) Counter.client_http.clients; + break; default: *ErrP = SNMP_ERR_NOSUCHNAME; snmp_var_free(Answer); @@ -436,7 +413,12 @@ return Answer; case PERF_PROTOSTAT_MEDIAN: - minutes = Var->name[LEN_SQ_PRF + 4]; + if (Var->name_length == LEN_SQ_PRF + 5) + minutes = Var->name[LEN_SQ_PRF + 4]; + else + break; + if ((minutes < 1) || (minutes > 60)) + break; f = snmpStatGet(0); l = snmpStatGet(minutes); @@ -477,6 +459,12 @@ case PERF_MEDIAN_DNS: x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time); break; + case PERF_MEDIAN_RHR: + x = statRequestHitRatio(minutes); + break; + case PERF_MEDIAN_BHR: + x = statByteHitRatio(minutes); + break; default: *ErrP = SNMP_ERR_NOSUCHNAME; snmp_var_free(Answer); @@ -489,26 +477,3 @@ snmp_var_free(Answer); return (NULL); } - -void -addr2oid(struct in_addr addr, oid * Dest) -{ - u_char *cp; - cp = (u_char *) & (addr.s_addr); - Dest[0] = *cp++; - Dest[1] = *cp++; - Dest[2] = *cp++; - Dest[3] = *cp++; -} - -struct in_addr * -oid2addr(oid * id) -{ - static struct in_addr laddr; - u_char *cp = (u_char *) & (laddr.s_addr); - cp[0] = id[0]; - cp[1] = id[1]; - cp[2] = id[2]; - cp[3] = id[3]; - return &laddr; -} Index: squid/src/snmp_core.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/snmp_core.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/snmp_core.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/snmp_core.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,8 +1,9 @@ + /* - * $Id: snmp_core.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: snmp_core.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 49 SNMP support - * AUTHOR: Kostas Anagnostakis + * AUTHOR: Glenn Chisholm * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- @@ -20,300 +21,329 @@ * 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. * */ - -/********************************************************************** - * - * Copyright 1996 by Carnegie Mellon University - * - * All Rights Reserved - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notice appear in all copies and that - * both that copyright notice and this permission notice appear in - * supporting documentation, and that the name of CMU not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * - * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING - * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHAL - * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR - * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - * Author: Ryan Troll - * - **********************************************************************/ - - #include "squid.h" - #include "cache_snmp.h" -#include "squid_mib.h" #define SNMP_REQUEST_SIZE 4096 #define MAX_PROTOSTAT 5 -int snmp_dump_packet; -void *users, *communities; - -static struct sockaddr_in local_snmpd; -static int snmp_init_config = 0; -struct snmp_session *Session; -struct snmp_pdu *snmpAgentResponse(struct snmp_pdu *PDU); - -void snmpFwd_insertPending(struct sockaddr_in *, long); -int snmpFwd_removePending(struct sockaddr_in *, long); +typedef struct _mib_tree_entry mib_tree_entry; +typedef oid *(instance_Fn) (oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn); -extern void (*snmplib_debug_hook) (int, char *); -static void snmpSnmplibDebug(int lvl, char *buf); - -struct snmpUdpData { - struct sockaddr_in address; - void *msg; +struct _mib_tree_entry { + oid *name; int len; - struct snmpUdpData *next; + oid_ParseFn *parsefunction; + instance_Fn *instancefunction; + int children; + struct _mib_tree_entry **leaves; + struct _mib_tree_entry *parent; }; -typedef struct snmpUdpData snmpUdpData; - -struct snmpFwdQueue { - struct sockaddr_in addr; - long req_id; - time_t req_time; - struct snmpFwdQueue *next; -}; +mib_tree_entry *mib_tree_head; +mib_tree_entry *mib_tree_last; -struct snmpFwdQueue *snmpHead = NULL; - -struct snmpUdpData *snmpUdpHead = NULL; -struct snmpUdpData *snmpUdpTail = NULL; - -void snmpUdpReply(int, void *); -void snmpAppendUdp(snmpUdpData *); -void snmpUdpSend(int, const struct sockaddr_in *, void *, int); - -/* now include mib location definitions - * and magic numbers */ - -#include "cache_snmp.h" +#if STDC_HEADERS +static mib_tree_entry *snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...); +static oid *snmpCreateOid(int length,...); +#else +static mib_tree_entry *snmpAddNode(); +static oid *snmpCreateOid(); +#endif +extern void (*snmplib_debug_hook) (int, char *); +static oid *static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn); +static oid *time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn); +static oid *peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn); +static oid *client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn); +static void snmpDecodePacket(snmp_request_t * rq); +static void snmpConstructReponse(snmp_request_t * rq); +static struct snmp_pdu *snmpAgentResponse(struct snmp_pdu *PDU); +static oid_ParseFn *snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen); +static oid_ParseFn *snmpTreeGet(oid * Current, snint CurrentLen); +static mib_tree_entry *snmpTreeEntry(oid entry, snint len, mib_tree_entry * current); +static mib_tree_entry *snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current); +static oid *snmpOidDup(oid * A, snint ALen); +static void snmpSnmplibDebug(int lvl, char *buf); -static void -snmpSnmplibDebug(int lvl, char *buf) -{ - debug(49, lvl) ("%s", buf); -} +/* + * The functions used during startup: + * snmpInit + * snmpConnectionOpen + * snmpConnectionShutdown + * snmpConnectionClose + */ +/* + * Turns the MIB into a Tree structure. Called during the startup process. + */ void -snmpHandleUdp(int sock, void *not_used) +snmpInit(void) { - struct sockaddr_in from; - socklen_t from_len; - LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE); - LOCAL_ARRAY(char, deb_line, 4096); - int len; - snmp_request_t *snmp_rq; - - debug(49, 5) ("snmpHandleUdp: Called.\n"); - commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0); - from_len = sizeof(struct sockaddr_in); - memset(&from, '\0', from_len); - Counter.syscalls.sock.recvfroms++; - len = recvfrom(sock, - buf, - SNMP_REQUEST_SIZE, - 0, - (struct sockaddr *) &from, - &from_len); - if (len < 0) { -#ifdef _SQUID_LINUX_ - /* Some Linux systems seem to set the FD for reading and then - * return ECONNREFUSED when sendto() fails and generates an ICMP - * port unreachable message. */ - /* or maybe an EHOSTUNREACH "No route to host" message */ - if (errno != ECONNREFUSED && errno != EHOSTUNREACH) -#endif - debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n", - sock, xstrerror()); - return; - } - if (snmp_dump_packet) { - int count; - debug(49, 6) ("received %d bytes from %s:\n", (int) len, - inet_ntoa(from.sin_addr)); - for (count = 0; count < len; count++) { - snprintf(deb_line, 4096, "%s %02X ", deb_line, (u_char) buf[count]); - if ((count % 16) == 15 || count == (len - 1)) { - debug(49, 8) ("snmp in: %s\n", deb_line); - deb_line[0] = '\0'; - } - } - } - buf[len] = '\0'; - debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n", - sock, - len, - inet_ntoa(from.sin_addr)); - - snmp_rq = xcalloc(1, sizeof(snmp_request_t)); - snmp_rq->buf = (u_char *) buf; - snmp_rq->len = len; - snmp_rq->sock = sock; - snmp_rq->outbuf = xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE); - memcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in)); - snmpAgentParse(snmp_rq); -} + debug(49, 5) ("snmpInit: Called.\n"); -void -snmpAgentParseDone(int errstat, void *data) -{ - snmp_request_t *snmp_rq = (snmp_request_t *) data; - LOCAL_ARRAY(char, deb_line, 4096); - int sock = snmp_rq->sock; - long this_reqid = snmp_rq->reqid; - debug(49, 2) ("snmpAgentParseDone: errstat=%d, reqid=%d _t=%x\n", - errstat, this_reqid, snmp_rq); - - if (memcmp(&snmp_rq->from, &local_snmpd, sizeof(struct sockaddr_in)) == 0) { - /* look it up */ - if (snmpFwd_removePending(&snmp_rq->from, this_reqid)) { /* failed */ - debug(49, 2) ("snmp: bogus response from %s.\n", - inet_ntoa(snmp_rq->from.sin_addr)); - if (snmp_rq->community) - xfree(snmp_rq->community); - xfree(snmp_rq->outbuf); - xfree(snmp_rq); - return; - } - } - switch (errstat) { - case 2: /* we might have to forward */ - if (Config.Snmp.localPort != 0) { - snmpFwd_insertPending(&snmp_rq->from, this_reqid); - snmpUdpSend(sock, &local_snmpd, snmp_rq->outbuf, snmp_rq->outlen); - break; - } - debug(49, 4) ("snmp: can't forward.\n"); - break; - case 1: /* everything is ok */ - debug(49, 5) ("snmp: parsed.\n"); - if (snmp_dump_packet) { - int count = 0; - debug(49, 5) ("snmp: sent %d bytes to %s\n", (int) snmp_rq->outlen, - inet_ntoa(snmp_rq->from.sin_addr)); - for (count = 0; count < snmp_rq->outlen; count++) { - snprintf(deb_line, 4096, "%s %02X ", deb_line, - (u_char) snmp_rq->outbuf[count]); - if ((count % 16) == 15 || count == (snmp_rq->len - 1)) { - debug(49, 7) ("snmp out: %s\n", deb_line); - deb_line[0] = '\0'; - } - } - } - snmpUdpSend(snmp_rq->sock, &snmp_rq->from, snmp_rq->outbuf, snmp_rq->outlen); - break; - case 0: - debug(49, 5) ("snmpagentparsedone failed\n"); - if (snmp_rq->outbuf) - xfree(snmp_rq->outbuf); - break; - } - if (snmp_rq->community) - xfree(snmp_rq->community); - cbdataFree(snmp_rq); - return; -} + debug(49, 5) ("snmpInit: Building SNMP mib tree structure\n"); -void -snmpInit(void) -{ - assert(NULL != Config.Snmp.mibPath); - if (!snmpInitConfig()) - debug(49, 0) ("snmpInit: snmpInitConfig() failed.\n"); snmplib_debug_hook = snmpSnmplibDebug; -} -int -snmpInitConfig() -{ - wordlist *w; - char *buf; - char *tokens[10]; - - if (snmp_init_config) - return 1; - - snmp_init_config = 1; - assert(NULL != Config.Snmp.mibPath); - if (Mib == NULL) { - debug(49, 3) ("init_mib: calling with %s\n", Config.Snmp.mibPath); - init_mib(Config.Snmp.mibPath); - } - if (Mib == NULL) { - debug(49, 0) ("WARNING: Failed to open MIB '%s'\n", - Config.Snmp.mibPath); - return 0; - } - /* - * Process 'snmp_agent_conf' lines - */ - for (w = Config.Snmp.snmpconf; w != NULL; w = w->next) { - buf = xstrdup(w->key); - snmpTokenize(buf, tokens, 10); - if (0 == strcmp("view", tokens[0])) { - if (snmpCreateView(tokens) < 0) { - debug(49, 1) ("snmpInit: error parsing '%s'\n", w->key); - safe_free(buf); - return 0; - } - } else if (0 == strcmp("user", tokens[0])) { - if (snmpCreateUser(tokens) < 0) { - debug(49, 1) ("snmpInit: error parsing '%s'\n", w->key); - safe_free(buf); - return 0; - } - } else if (0 == strcmp("community", tokens[0])) { - if (snmpCreateCommunity(tokens) < 0) - debug(49, 1) ("snmpInit: error parsing '%s'\n", w->key); - } else { - debug(49, 1) ("snmpInit: error parsing '%s'\n", w->key); - safe_free(buf); - return 0; - } - safe_free(buf); - } - if (!Config.Snmp.communities) { - debug(49, 2) ("snmpInit: WARNING: communities not defined.\n"); - } else - debug(49, 5) ("snmpInit: communities defined.\n"); - snmpInitAgentAuth(); - assert(0 <= snmpDefaultAuth()); - return 1; + mib_tree_head = snmpAddNode(snmpCreateOid(1, 1), + 1, NULL, NULL, 1, + snmpAddNode(snmpCreateOid(2, 1, 3), + 2, NULL, NULL, 1, + snmpAddNode(snmpCreateOid(3, 1, 3, 6), + 3, NULL, NULL, 1, + snmpAddNode(snmpCreateOid(4, 1, 3, 6, 1), + 4, NULL, NULL, 1, + snmpAddNode(snmpCreateOid(5, 1, 3, 6, 1, 4), + 5, NULL, NULL, 1, + snmpAddNode(snmpCreateOid(6, 1, 3, 6, 1, 4, 1), + 6, NULL, NULL, 1, + snmpAddNode(snmpCreateOid(7, 1, 3, 6, 1, 4, 1, 3495), + 7, NULL, NULL, 1, + snmpAddNode(snmpCreateOid(LEN_SQUIDMIB, SQUIDMIB), + 8, NULL, NULL, 5, + snmpAddNode(snmpCreateOid(LEN_SQ_SYS, SQ_SYS), + LEN_SQ_SYS, NULL, NULL, 3, + snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYSVMSIZ), + LEN_SYS, snmp_sysFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYSSTOR), + LEN_SYS, snmp_sysFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYS_UPTIME), + LEN_SYS, snmp_sysFn, static_Inst, 0)), + snmpAddNode(snmpCreateOid(LEN_SQ_CONF, SQ_CONF), + LEN_SQ_CONF, NULL, NULL, 5, + snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_ADMIN), + LEN_SYS, snmp_confFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_VERSION), + LEN_SYS, snmp_confFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_VERSION_ID), + LEN_SYS, snmp_confFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_LOG_FAC), + LEN_SYS, snmp_confFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_STORAGE), + LEN_SYS, NULL, NULL, 4, + snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_MMAXSZ), + LEN_CONF_ST, snmp_confFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWMAXSZ), + LEN_CONF_ST, snmp_confFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWHIWM), + LEN_CONF_ST, snmp_confFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWLOWM), + LEN_CONF_ST, snmp_confFn, static_Inst, 0))), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF, SQ_PRF), + LEN_SQ_PRF, NULL, NULL, 2, + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_SYS), + LEN_SQ_PRF + 1, NULL, NULL, 11, + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 1), + LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 2), + LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 3), + LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 4), + LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 5), + LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 6), + LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 7), + LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 8), + LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 9), + LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 10), + LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 11), + LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0)), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_PROTO), + LEN_SQ_PRF + 1, NULL, NULL, 2, + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, 1), + LEN_SQ_PRF + 2, NULL, NULL, 15, + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 1), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 2), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 3), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 4), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 5), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 6), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 7), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 8), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 9), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 10), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 11), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 12), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 13), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 14), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 15), + LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0)), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, 2), + LEN_SQ_PRF + 2, NULL, NULL, 1, + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 2, 1), + LEN_SQ_PRF + 3, NULL, NULL, 10, + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 1), + LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 2), + LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 3), + LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 4), + LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 5), + LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 6), + LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 7), + LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 8), + LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 9), + LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 10), + LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0))))), + snmpAddNode(snmpCreateOid(LEN_SQ_NET, SQ_NET), + LEN_SQ_NET, NULL, NULL, 3, + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_IP_CACHE), + LEN_SQ_NET + 1, NULL, NULL, 8, + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_ENT), + LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_REQ), + LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_HITS), + LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_PENDHIT), + LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_NEGHIT), + LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_MISS), + LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_GHBN), + LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_LOC), + LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0)), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_FQDN_CACHE), + LEN_SQ_NET + 1, NULL, NULL, 7, + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_ENT), + LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_REQ), + LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_HITS), + LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_PENDHIT), + LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_NEGHIT), + LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_MISS), + LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_GHBN), + LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0)), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_DNS_CACHE), + LEN_SQ_NET + 1, NULL, NULL, 3, + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REQ), + LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REP), + LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_SERVERS), + LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0))), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH, SQ_MESH), + LEN_SQ_MESH, NULL, NULL, 2, + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 1), + LEN_SQ_MESH + 1, NULL, NULL, 1, + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 1, 1), + LEN_SQ_MESH + 2, NULL, NULL, 13, + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 1), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 2), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 3), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 4), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 5), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 6), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 7), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 8), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 9), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 10), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 11), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 12), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 13), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0))), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 2), + LEN_SQ_MESH + 1, NULL, NULL, 1, + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 2, 1), + LEN_SQ_MESH + 2, NULL, NULL, 9, + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 1), + LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 2), + LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 3), + LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 4), + LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 5), + LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 6), + LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 7), + LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 8), + LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), + (mib_tree_last = snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 9), + LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0))))) + ) + ) + ) + ) + ) + ) + ) + ); + + debug(49, 9) ("snmpInit: Completed SNMP mib tree structure\n"); } void snmpConnectionOpen(void) { u_short port; - struct in_addr addr; struct sockaddr_in xaddr; socklen_t len; int x; + debug(49, 5) ("snmpConnectionOpen: Called\n"); if ((port = Config.Port.snmp) > (u_short) 0) { enter_suid(); theInSnmpConnection = comm_open(SOCK_DGRAM, @@ -328,11 +358,11 @@ commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0); debug(1, 1) ("Accepting SNMP messages on port %d, FD %d.\n", (int) port, theInSnmpConnection); - if ((addr = Config.Addrs.snmp_outgoing).s_addr != no_addr.s_addr) { + if (Config.Addrs.snmp_outgoing.s_addr != no_addr.s_addr) { enter_suid(); theOutSnmpConnection = comm_open(SOCK_DGRAM, 0, - addr, + Config.Addrs.snmp_outgoing, port, COMM_NONBLOCKING, "SNMP Port"); @@ -358,118 +388,12 @@ if (x < 0) debug(51, 1) ("theOutSnmpConnection FD %d: getsockname: %s\n", theOutSnmpConnection, xstrerror()); - else { + else theOutSNMPAddr = xaddr.sin_addr; - if (Config.Snmp.localPort != 0) { - local_snmpd.sin_addr = xaddr.sin_addr; - local_snmpd.sin_port = Config.Snmp.localPort; - } - } } } void -snmpFwd_insertPending(struct sockaddr_in *ad, long reqid) -{ - struct snmpFwdQueue *new; - - new = (struct snmpFwdQueue *) xcalloc(1, sizeof(struct snmpFwdQueue)); - xmemcpy(&new->addr, ad, sizeof(struct sockaddr_in)); - new->req_id = reqid; - new->req_time = squid_curtime; - if (snmpHead == NULL) { - new->next = NULL; - snmpHead = new; - } - new->next = snmpHead; - snmpHead = new; -} - -int -snmpFwd_removePending(struct sockaddr_in *fr, long reqid) -{ - struct snmpFwdQueue *p, *prev = NULL; - for (p = snmpHead; p != NULL; p = p->next, prev = p) - if (reqid == p->req_id) { - xmemcpy(fr, &p->addr, sizeof(struct sockaddr_in)); - if (p == snmpHead) - snmpHead = p->next; - else if (p->next == NULL) - prev->next = NULL; - debug(49, 3) ("snmpFwd_removePending: freeing %p\n", p); - xfree(p); - return 0; - } - return 1; -} - -void -snmpUdpSend(int fd, - const struct sockaddr_in *to, - void *msg, int len) -{ - snmpUdpData *data = xcalloc(1, sizeof(snmpUdpData)); - debug(49, 5) ("snmpUdpSend: Queueing response for %s\n", - inet_ntoa(to->sin_addr)); - data->address = *to; - data->msg = msg; - data->len = len; - snmpAppendUdp(data); - commSetSelect(fd, COMM_SELECT_WRITE, snmpUdpReply, snmpUdpHead, 0); - -} -void -snmpUdpReply(int fd, void *data) -{ - snmpUdpData *queue = data; - int x; - /* Disable handler, in case of errors. */ - commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0); - while ((queue = snmpUdpHead) != NULL) { - debug(49, 5) ("snmpUdpReply: FD %d sending %d bytes to %s port %d\n", - fd, - queue->len, - inet_ntoa(queue->address.sin_addr), - ntohs(queue->address.sin_port)); - x = comm_udp_sendto(fd, - &queue->address, - sizeof(struct sockaddr_in), - queue->msg, - queue->len); - if (x < 0) { - if (ignoreErrno(errno)) - break; /* don't de-queue */ - } - snmpUdpHead = queue->next; - debug(49, 3) ("snmpUdpReply: freeing %p\n", queue->msg); - safe_free(queue->msg); - debug(49, 3) ("snmpUdpReply: freeing %p\n", queue); - safe_free(queue); - } - /* Reinstate handler if needed */ - if (snmpUdpHead) { - commSetSelect(fd, COMM_SELECT_WRITE, snmpUdpReply, snmpUdpHead, 0); - } -} - -void -snmpAppendUdp(snmpUdpData * item) -{ - item->next = NULL; - if (snmpUdpHead == NULL) { - snmpUdpHead = item; - snmpUdpTail = item; - } else if (snmpUdpTail == snmpUdpHead) { - snmpUdpTail = item; - snmpUdpHead->next = item; - } else { - snmpUdpTail->next = item; - snmpUdpTail = item; - } - -} - -void snmpConnectionShutdown(void) { if (theInSnmpConnection < 0) @@ -484,7 +408,7 @@ * function from executing repeatedly. When we are really ready to * exit or restart, main will comm_close the 'out' descriptor. */ theInSnmpConnection = -1; - /* + /* * Normally we only write to the outgoing SNMP socket, but we * also have a read handler there to catch messages sent to that * specific interface. During shutdown, we must disable reading @@ -504,346 +428,632 @@ } } -/* returns: - * 2: no such object in this mib - * 1: ok - * 0: failed */ +/* + * Functions for handling the requests. + */ +/* + * Accept the UDP packet + */ void -snmpAgentParse(void *data) +snmpHandleUdp(int sock, void *not_used) { - snmp_request_t *rq = (snmp_request_t *) data; - u_char *buf = rq->buf; - int len = rq->len; + LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE); + struct sockaddr_in from; + socklen_t from_len; + snmp_request_t *snmp_rq; + int len; + + debug(49, 5) ("snmpHandleUdp: Called.\n"); + + commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0); + from_len = sizeof(struct sockaddr_in); + memset(&from, '\0', from_len); + memset(buf, '\0', SNMP_REQUEST_SIZE); + + Counter.syscalls.sock.recvfroms++; + + len = recvfrom(sock, + buf, + SNMP_REQUEST_SIZE, + 0, + (struct sockaddr *) &from, + &from_len); + if (len > 0) { + buf[len] = '\0'; + debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n", + sock, + len, + inet_ntoa(from.sin_addr)); + + snmp_rq = xcalloc(1, sizeof(snmp_request_t)); + snmp_rq->buf = (u_char *) buf; + snmp_rq->len = len; + snmp_rq->sock = sock; + snmp_rq->outbuf = xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE); + xmemcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in)); + snmpDecodePacket(snmp_rq); + xfree(snmp_rq); + } else { + debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n", sock, xstrerror()); + } +} + +/* + * Turn SNMP packet into a PDU, check available ACL's + */ +void +snmpDecodePacket(snmp_request_t * rq) +{ struct snmp_pdu *PDU; + struct snmp_session Session; + aclCheck_t checklist; u_char *Community; + u_char *buf = rq->buf; + int len = rq->len; + int allow = 0; + debug(49, 5) ("snmpDecodePacket: Called.\n"); /* Now that we have the data, turn it into a PDU */ - cbdataAdd(rq, MEM_NONE); PDU = snmp_pdu_create(0); - Community = snmp_parse(Session, PDU, buf, len); + Session.Version = SNMP_VERSION_1; + Community = snmp_parse(&Session, PDU, buf, len); + + checklist.src_addr = rq->from.sin_addr; + checklist.snmp_community = (char *) Community; - if (!snmp_coexist_V2toV1(PDU)) { /* incompatibility */ - debug(49, 3) ("snmpAgentParse: Incompatible V2 packet.\n"); + allow = aclCheckFast(Config.accessList.snmp, &checklist); + if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) { + rq->community = Community; + rq->PDU = PDU; + debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid); + snmpConstructReponse(rq); + } else { + debug(49, 1) ("Failed SNMP agent query from : %s.\n", + inet_ntoa(rq->from.sin_addr)); snmp_free_pdu(PDU); - snmpAgentParseDone(0, rq); - return; } - rq->community = Community; - rq->PDU = PDU; - debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid); +} - if (!Community) { - debug(49, 2) ("snmpAgentParse: WARNING: Could not parse community\n"); +/* + * Packet OK, ACL Check OK, Create reponse. + */ +void +snmpConstructReponse(snmp_request_t * rq) +{ + struct snmp_session Session; + struct snmp_pdu *RespPDU; + int ret; - snmp_free_pdu(PDU); - snmpAgentParseDone(0, rq); - return; + debug(49, 5) ("snmpConstructReponse: Called.\n"); + RespPDU = snmpAgentResponse(rq->PDU); + snmp_free_pdu(rq->PDU); + if (RespPDU != NULL) { + Session.Version = SNMP_VERSION_1; + Session.community = rq->community; + Session.community_len = strlen((char *) rq->community); + ret = snmp_build(&Session, RespPDU, rq->outbuf, &rq->outlen); + sendto(rq->sock, rq->outbuf, rq->outlen, 0, (struct sockaddr *) &rq->from, sizeof(rq->from)); + snmp_free_pdu(RespPDU); + xfree(rq->outbuf); } - snmpAclCheckStart(rq); } +/* + * Decide how to respond to the request, construct a response and + * return the response to the requester. + * + * If configured forward any reponses which are not for this agent. + */ struct snmp_pdu * snmpAgentResponse(struct snmp_pdu *PDU) { struct snmp_pdu *Answer = NULL; - variable_list *VarPtr, *VarNew = NULL; - variable_list **VarPtrP, **RespVars; - int index = 0; - oid_ParseFn *ParseFn; + oid_ParseFn *ParseFn = NULL; - debug(49, 9) ("snmpAgentResponse: Received a %d PDU\n", PDU->command); + variable_list *VarPtr, *VarNew = NULL, **VarPtrP; + int index = 0; - /* Create a response */ - Answer = snmp_pdu_create(SNMP_PDU_RESPONSE); - if (Answer == NULL) - return (NULL); - Answer->reqid = PDU->reqid; - Answer->errindex = 0; - - if (PDU->command == SNMP_PDU_GET) { - - RespVars = &(Answer->variables); - /* Loop through all variables */ - for (VarPtrP = &(PDU->variables); - *VarPtrP; - VarPtrP = &((*VarPtrP)->next_variable)) { - VarPtr = *VarPtrP; + debug(49, 5) ("snmpAgentResponse: Called.\n"); - index++; + if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE))) { + Answer->reqid = PDU->reqid; + Answer->errindex = 0; + if (PDU->command == SNMP_PDU_GET) { + variable_list **RespVars; + + RespVars = &(Answer->variables); + /* Loop through all variables */ + for (VarPtrP = &(PDU->variables); + *VarPtrP; + VarPtrP = &((*VarPtrP)->next_variable)) { + VarPtr = *VarPtrP; + + index++; + + /* Find the parsing function for this variable */ + ParseFn = snmpTreeGet(VarPtr->name, VarPtr->name_length); + + if (ParseFn == NULL) { + Answer->errstat = SNMP_ERR_NOSUCHNAME; + debug(49, 5) ("snmpAgentResponse: No such oid. "); + } else + VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat)); + + /* Was there an error? */ + if ((Answer->errstat != SNMP_ERR_NOERROR) || + (VarNew == NULL)) { + Answer->errindex = index; + debug(49, 5) ("snmpAgentParse: successful.\n"); + /* Just copy the rest of the variables. Quickly. */ + *RespVars = VarPtr; + *VarPtrP = NULL; + return (Answer); + } + /* No error. Insert this var at the end, and move on to the next. + */ + *RespVars = VarNew; + RespVars = &(VarNew->next_variable); + } + return (Answer); + } else if (PDU->command == SNMP_PDU_GETNEXT) { + oid *NextOidName = NULL; + int NextOidNameLen = 0; - /* Find the parsing function for this variable */ - ParseFn = oidlist_Find(VarPtr->name, VarPtr->name_length); + ParseFn = snmpTreeNext(PDU->variables->name, PDU->variables->name_length, + &(NextOidName), (snint *) & NextOidNameLen); if (ParseFn == NULL) { Answer->errstat = SNMP_ERR_NOSUCHNAME; - debug(49, 5) ("snmpAgentResponse: No such oid. "); - } else - VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat)); + debug(49, 5) ("snmpAgentResponse: No such oid: "); + snmpDebugOid(5, PDU->variables->name, PDU->variables->name_length); + } else { + xfree(PDU->variables->name); + PDU->variables->name = NextOidName; + PDU->variables->name_length = NextOidNameLen; + VarNew = (*ParseFn) (PDU->variables, (snint *) & Answer->errstat); + } /* Was there an error? */ - if ((Answer->errstat != SNMP_ERR_NOERROR) || - (VarNew == NULL)) { - Answer->errindex = index; - debug(49, 5) ("snmpAgentParse: successful.\n"); - /* Just copy the rest of the variables. Quickly. */ - *RespVars = VarPtr; - *VarPtrP = NULL; - return (Answer); + if (Answer->errstat != SNMP_ERR_NOERROR) { + Answer->errindex = 1; + Answer->variables = PDU->variables; + PDU->variables = NULL; + } else { + Answer->variables = VarNew; } - /* No error. Insert this var at the end, and move on to the next. - */ - *RespVars = VarNew; - RespVars = &(VarNew->next_variable); - } - return (Answer); - } else if (PDU->command == SNMP_PDU_GETNEXT) { - oid *TmpOidName; - int TmpOidNameLen = 0; - - /* Find the next OID. */ - VarPtr = PDU->variables; - - ParseFn = oidlist_Next(VarPtr->name, VarPtr->name_length, - &(TmpOidName), (snint *) & (TmpOidNameLen)); - - if (ParseFn == NULL) { - Answer->errstat = SNMP_ERR_NOSUCHNAME; - debug(49, 5) ("snmpAgentResponse: No such oid: "); - snmpDebugOid(5, VarPtr->name, VarPtr->name_length); - } else { - xfree(VarPtr->name); - VarPtr->name = TmpOidName; - VarPtr->name_length = TmpOidNameLen; - VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat)); - } - /* Was there an error? */ - if (Answer->errstat != SNMP_ERR_NOERROR) { - Answer->errindex = 1; - - /* Just copy this variable */ - Answer->variables = VarPtr; - PDU->variables = NULL; } else { - Answer->variables = VarNew; + snmp_free_pdu(Answer); + Answer = NULL; } - - /* Done. Return this PDU */ - return (Answer); - } /* end SNMP_PDU_GETNEXT */ - debug(49, 5) ("snmpAgentResponse: Ignoring PDU %d unknown command\n", PDU->command); - snmp_free_pdu(Answer); - return (NULL); + } + return (Answer); } -void -snmpDebugOid(int lvl, oid * Name, snint Len) +oid_ParseFn * +snmpTreeGet(oid * Current, snint CurrentLen) { - char mbuf[16], objid[1024]; - int x; - objid[0] = '\0'; + oid_ParseFn *Fn = NULL; + mib_tree_entry *mibTreeEntry = NULL, *lastEntry = NULL; + int count = 0; - for (x = 0; x < Len; x++) { - snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]); - strncat(objid, mbuf, sizeof(objid)); - } + debug(49, 5) ("snmpTreeGet: Called\n"); - debug(49, lvl) (" oid = %s\n", objid); -} + debug(49, 6) ("snmpTreeGet: Current : \n"); + snmpDebugOid(6, Current, CurrentLen); -int -oidcmp(oid * A, snint ALen, oid * B, snint BLen) -{ - oid *aptr = A; - oid *bptr = B; - snint m = MIN(ALen, BLen); - - /* Compare the first M bytes. */ - while (m) { - if (*aptr < *bptr) - return (-1); - if (*aptr++ > *bptr++) - return (1); - m--; + mibTreeEntry = mib_tree_head; + if (Current[count] == mibTreeEntry->name[count]) { + count++; + while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) { + lastEntry = mibTreeEntry; + mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry); + count++; + } } + if (mibTreeEntry && mibTreeEntry->parsefunction) + Fn = mibTreeEntry->parsefunction; + debug(49, 5) ("snmpTreeGet: return\n"); + return (Fn); +} - /* The first M bytes were identical. So, they share the same - * root. The shorter one must come first. - */ - if (ALen < BLen) - return (-1); +oid_ParseFn * +snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen) +{ + oid_ParseFn *Fn = NULL; + mib_tree_entry *mibTreeEntry = NULL, *nextoid = NULL; + int count = 0; - if (ALen > BLen) - return (1); + debug(49, 5) ("snmpTreeNext: Called\n"); - /* Same length, all bytes identical. Must be the same OID. */ - return (0); -} + debug(49, 6) ("snmpTreeNext: Current : \n"); + snmpDebugOid(6, Current, CurrentLen); -int -oidncmp(oid * A, snint ALen, oid * B, snint BLen, snint CompLen) -{ - oid *aptr = A; - oid *bptr = B; - snint m = MIN(MIN(ALen, BLen), CompLen); - snint count = 0; - - /* Compare the first M bytes. */ - while (count != m) { - if (*aptr < *bptr) - return (-1); - if (*aptr++ > *bptr++) - return (1); + mibTreeEntry = mib_tree_head; + if (Current[count] == mibTreeEntry->name[count]) { count++; + while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) { + mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry); + count++; + } + debug(49, 5) ("snmpTreeNext: Recursed down to requested object\n"); + } else { + return NULL; } + if (mibTreeEntry == mib_tree_last) + return (Fn); + if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) { + *NextLen = CurrentLen; + *Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn); + if (*Next) + return (Fn); + } + if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) { + count--; + nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent); + if (nextoid) { + debug(49, 5) ("snmpTreeNext: Next OID found for sibling\n"); + mibTreeEntry = nextoid; + count++; + } else { + debug(49, 5) ("snmpTreeNext: Attempting to recurse up for next object\n"); + while (!nextoid) { + count--; + if (mibTreeEntry->parent->parent) { + nextoid = mibTreeEntry->parent; + mibTreeEntry = snmpTreeEntry(Current[count] + 1, count, nextoid->parent); + if (!mibTreeEntry) { + mibTreeEntry = nextoid; + nextoid = NULL; + } + } else { + nextoid = mibTreeEntry; + mibTreeEntry = NULL; + } + } + } + } + while ((mibTreeEntry) && (!mibTreeEntry->parsefunction)) { + mibTreeEntry = mibTreeEntry->leaves[0]; + } + if (mibTreeEntry) { + *NextLen = mibTreeEntry->len; + *Next = (*mibTreeEntry->instancefunction) (mibTreeEntry->name, NextLen, mibTreeEntry, &Fn); + } + return (Fn); +} - if (m == CompLen) - return (0); - - - if (ALen < BLen) - return (-1); +oid * +static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn) +{ + oid *instance = NULL; - if (ALen > BLen) - return (1); + if (*len <= current->len) { + instance = xmalloc(sizeof(name) * (*len + 1)); + xmemcpy(instance, name, (sizeof(name) * *len)); + instance[*len] = 0; + *len += 1; + } + *Fn = current->parsefunction; + return (instance); +} - /* Same length, all bytes identical. Must be the same OID. */ - return (0); +oid * +time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn) +{ + oid *instance = NULL; + int identifier = 0, loop = 0; + int index[TIME_INDEX_LEN] = + {TIME_INDEX}; + + if (*len <= current->len) { + instance = xmalloc(sizeof(name) * (*len + 1)); + xmemcpy(instance, name, (sizeof(name) * *len)); + instance[*len] = *index; + *len += 1; + } else { + identifier = name[*len - 1]; + while ((identifier != index[loop]) && (loop < TIME_INDEX_LEN)) + loop++; + if (loop < TIME_INDEX_LEN - 1) { + instance = xmalloc(sizeof(name) * (*len)); + xmemcpy(instance, name, (sizeof(name) * *len)); + instance[*len - 1] = index[++loop]; + } + } + *Fn = current->parsefunction; + return (instance); } -/* Allocate space for, and copy, an OID. Returns new oid, or NULL. - */ oid * -oiddup(oid * A, snint ALen) +peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn) { - oid *Ans; + oid *instance = NULL; + u_char *cp = NULL; + peer *peers = Config.peers; + struct in_addr *laddr = NULL; + char *host_addr = NULL, *current_addr = NULL, *last_addr = NULL; + + if (peers == NULL) { + current = current->parent->parent->parent->leaves[1]; + while ((current) && (!current->parsefunction)) + current = current->leaves[0]; + instance = client_Inst(current->name, len, current, Fn); + } else if (*len <= current->len) { + instance = xmalloc(sizeof(name) * (*len + 4)); + xmemcpy(instance, name, (sizeof(name) * *len)); + cp = (u_char *) & (peers->in_addr.sin_addr.s_addr); + instance[*len] = *cp++; + instance[*len + 1] = *cp++; + instance[*len + 2] = *cp++; + instance[*len + 3] = *cp++; + *len += 4; + } else { + laddr = oid2addr(&name[*len - 4]); + host_addr = inet_ntoa(*laddr); + last_addr = xmalloc(strlen(host_addr)); + strncpy(last_addr, host_addr, strlen(host_addr)); + current_addr = inet_ntoa(peers->in_addr.sin_addr); + while ((peers) && (strncmp(last_addr, current_addr, strlen(current_addr)))) { + if (peers->next) { + peers = peers->next; + current_addr = inet_ntoa(peers->in_addr.sin_addr); + } else { + peers = NULL; + } + } + xfree(last_addr); + if (peers) { + if (peers->next) { + peers = peers->next; + instance = xmalloc(sizeof(name) * (*len)); + xmemcpy(instance, name, (sizeof(name) * *len)); + cp = (u_char *) & (peers->in_addr.sin_addr.s_addr); + instance[*len - 4] = *cp++; + instance[*len - 3] = *cp++; + instance[*len - 2] = *cp++; + instance[*len - 1] = *cp++; + } else { + return (instance); + } + } else { + return (instance); + } + } + *Fn = current->parsefunction; + return (instance); +} - Ans = (oid *) xmalloc(sizeof(oid) * ALen); - if (Ans) - memcpy(Ans, A, (sizeof(oid) * ALen)); - return (Ans); +oid * +client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn) +{ + oid *instance = NULL; + u_char *cp = NULL; + struct in_addr *laddr = NULL; + + if (*len <= current->len) { + instance = xmalloc(sizeof(name) * (*len + 4)); + xmemcpy(instance, name, (sizeof(name) * *len)); + laddr = client_entry(NULL); + if (laddr) { + cp = (u_char *) & (laddr->s_addr); + instance[*len] = *cp++; + instance[*len + 1] = *cp++; + instance[*len + 2] = *cp++; + instance[*len + 3] = *cp++; + *len += 4; + } + } else { + laddr = oid2addr(&name[*len - 4]); + laddr = client_entry(laddr); + if (laddr) { + instance = xmalloc(sizeof(name) * (*len)); + xmemcpy(instance, name, (sizeof(name) * *len)); + cp = (u_char *) & (laddr->s_addr); + instance[*len - 4] = *cp++; + instance[*len - 3] = *cp++; + instance[*len - 2] = *cp++; + instance[*len - 1] = *cp++; + } + } + *Fn = current->parsefunction; + return (instance); } -/********************************************************************** - * OIDLIST FUNCTIONS - * - * Find the parsing function for OIDs registered in this agent. - **********************************************************************/ +/* + * Utility functions + */ -oid_ParseFn * -oidlist_Find(oid * Src, snint SrcLen) +/* + * Tree utility functions. + */ + +/* + * Returns a the sibling object in the tree + */ +mib_tree_entry * +snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current) { - struct MIBListEntry *Ptr; - int ret; + mib_tree_entry *next = NULL; + int count = 0; - debug(49, 7) ("oidlist_Find: Called.\n "); - snmpDebugOid(7, Src, SrcLen); + while ((!next) && (count < current->children)) { + if (current->leaves[count]->name[len] == entry) { + next = current->leaves[count]; + } + count++; + } + if (count < current->children) { + next = current->leaves[count]; + } else { + next = NULL; + } + return (next); +} - for (Ptr = squidMIBList; Ptr->GetFn; Ptr++) { +/* + * Returns the requested child object or NULL if it does not exist + */ +mib_tree_entry * +snmpTreeEntry(oid entry, snint len, mib_tree_entry * current) +{ + mib_tree_entry *next = NULL; + int count = 0; - ret = oidncmp(Src, SrcLen, Ptr->Name, Ptr->NameLen, Ptr->NameLen); + while ((!next) && (count < current->children)) { + if (current->leaves[count]->name[len] == entry) { + next = current->leaves[count]; + } + count++; + } + return (next); +} - if (!ret) { +/* + * Adds a node to the MIB tree structure and adds the appropriate children + */ +mib_tree_entry * +#if STDC_HEADERS +snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...) +#else +snmpAddNode(va_alist) + va_dcl +#endif +{ +#if STDC_HEADERS + va_list args; + int loop; + mib_tree_entry *entry = NULL; + va_start(args, children); +#else + va_list args; + oid *name = NULL; + int len = 0, children = 0, loop; + oid_ParseFn *parsefunction = NULL; + instance_Fn *instancefunction = NULL; + mib_tree_entry *entry = NULL; + va_start(args); + name = va_arg(args, oid *); + len = va_arg(args, int); + parsefunction = va_arg(args, oid_ParseFn *); + instancefunction = va_arg(args, instance_Fn *); + children = va_arg(args, int); +#endif - /* Cool. We found the mib it's in. Let it find the function. - */ - debug(49, 7) ("oidlist_Find: found, returning GetFn Ptr! \n"); + debug(49, 6) ("snmpAddNode: Children : %d, Oid : \n", children); + snmpDebugOid(6, name, len); - return ((*Ptr->GetFn) (Src, SrcLen)); - } - if (ret < 0) { - debug(49, 7) ("oidlist_Find: We just passed it, so it doesn't exist.\n "); - /* We just passed it, so it doesn't exist. */ - return (NULL); + va_start(args, children); + entry = xmalloc(sizeof(mib_tree_entry)); + entry->name = snmpOidDup(name, len); + entry->len = len; + entry->parsefunction = parsefunction; + entry->instancefunction = instancefunction; + entry->children = children; + + if (children > 0) { + entry->leaves = xmalloc(sizeof(mib_tree_entry *) * children); + for (loop = 0; loop < children; loop++) { + entry->leaves[loop] = va_arg(args, mib_tree_entry *); + entry->leaves[loop]->parent = entry; } } - - debug(49, 5) ("oidlist_Find: the request was past the end. It doesn't exist.\n"); - /* We get here if the request was past the end. It doesn't exist. */ - return (NULL); + return (entry); } -/* Find the next item. For SNMP_PDU_GETNEXT requests. - * - * Returns a pointer to the parser function, and copies the oid to dest. - * - * This is just plain ugly and needs a total rewrite, these changes are - * to make it work, nothing else! - * +/* End of tree utility functions */ + +/* + * Returns the list of parameters in an oid */ -oid_ParseFn * -oidlist_Next(oid * Src, snint SrcLen, oid ** DestP, snint * DestLenP) +oid * +#if STDC_HEADERS +snmpCreateOid(int length,...) +#else +snmpCreateOid(va_alist) + va_dcl +#endif { - struct MIBListEntry *Ptr; - int ret; - oid_ParseFn *Fn = NULL; +#if STDC_HEADERS + va_list args; + oid *new_oid; + int loop; + va_start(args, length); +#else + va_list args; + int length = 0, loop; + oid *new_oid; + va_start(args); + length va_arg(args, int); +#endif - debug(49, 7) ("oidlist_Next: Looking for next of:\n"); - snmpDebugOid(7, Src, SrcLen); + new_oid = xmalloc(sizeof(oid) * length); - for (Ptr = squidMIBList; Ptr->GetNextFn; Ptr++) { + if (length > 0) { + for (loop = 0; loop < length; loop++) { + new_oid[loop] = va_arg(args, int); + } + } + return (new_oid); +} - /* Only look at as much as we have stored */ - ret = oidncmp(Src, SrcLen, Ptr->Name, Ptr->NameLen, Ptr->NameLen); +/* + * Allocate space for, and copy, an OID. Returns new oid. + */ +oid * +snmpOidDup(oid * A, snint ALen) +{ + oid *Ans = xmalloc(sizeof(oid) * ALen); + xmemcpy(Ans, A, (sizeof(oid) * ALen)); + return Ans; +} - if (!ret) { - debug(49, 6) ("oidlist_Next: Checking MIB\n"); - - /* Cool. We found the mib it's in. Ask it. - */ - while (Ptr != NULL && Ptr->GetNextFn) { - Fn = ((*Ptr->GetNextFn) (Src, SrcLen, DestP, DestLenP)); - if (Fn == NULL) { - /* If this returned NULL, we're looking for the first - * in the next MIB. - */ - debug(49, 6) ("oidlist_Next: Not in this entry. Trying next.\n"); - Ptr++; - continue; - } - return Fn; - } - /* Return what we found. NULL if it wasn't in the MIB, and there - * were no more MIBs. - */ - debug(49, 3) ("oidlist_Next: No next mib.\n"); - return NULL; - } - if (ret < 0) { - /* We just passed the mib it would be in. Return - * the next in this MIB. - */ - debug(49, 3) ("oidlist_Next: Passed mib. Checking this one.\n"); - while (Ptr != NULL && Ptr->GetNextFn) { - Fn = ((*Ptr->GetNextFn) (Src, SrcLen, DestP, DestLenP)); - if (Fn == NULL && oidncmp(Src, SrcLen, Ptr->Name, Ptr->NameLen, Ptr->NameLen) < 0) { - debug(49, 6) ("oidlist_Next: Not in this entry. Trying next.\n"); - Ptr++; - continue; - } else { - return Fn; - } - } - debug(49, 3) ("oidlist_Next: No next mib.\n"); - return NULL; - } +/* + * Debug calls, prints out the OID for debugging purposes. + */ +void +snmpDebugOid(int lvl, oid * Name, snint Len) +{ + char mbuf[16], objid[1024]; + int x; + objid[0] = '\0'; + + for (x = 0; x < Len; x++) { + snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]); + strncat(objid, mbuf, sizeof(objid)); } - /* We get here if the request was past the end. It doesn't exist. */ - debug(49, 7) ("oidlist_Next: Found nothing.\n"); - return (NULL); + debug(49, lvl) (" oid = %s\n", objid); } -struct in_addr * -gen_getMax() +static void +snmpSnmplibDebug(int lvl, char *buf) { - static struct in_addr maddr; -#if USE_ICMP - safe_inet_addr("255.255.255.255", &maddr); -#else - safe_inet_addr("0.0.0.0", &maddr); -#endif - return &maddr; + debug(49, lvl) ("%s", buf); +} + +void +addr2oid(struct in_addr addr, oid * Dest) +{ + u_char *cp; + cp = (u_char *) & (addr.s_addr); + Dest[0] = *cp++; + Dest[1] = *cp++; + Dest[2] = *cp++; + Dest[3] = *cp++; +} + +struct in_addr + * +oid2addr(oid * id) +{ + static struct in_addr laddr; + u_char *cp = (u_char *) & (laddr.s_addr); + cp[0] = id[0]; + cp[1] = id[1]; + cp[2] = id[2]; + cp[3] = id[3]; + return &laddr; } Index: squid/src/squid.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/squid.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/squid.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/squid.h 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: squid.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: squid.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * AUTHOR: Duane Wessels * @@ -69,8 +69,11 @@ #endif #if PURIFY -/* disable assert() under purify */ -#define NODEBUG +#define assert(EX) ((void)0) +#elif STDC_HEADERS +#define assert(EX) ((EX)?((void)0):xassert( # EX , __FILE__, __LINE__)) +#else +#define assert(EX) ((EX)?((void)0):xassert("EX", __FILE__, __LINE__)) #endif #if HAVE_UNISTD_H @@ -172,11 +175,6 @@ #if HAVE_GETOPT_H #include #endif -#if HAVE_ASSERT_H -#include -#else -#define assert(X) ((void)0) -#endif #if HAVE_DIRENT_H #include @@ -214,7 +212,7 @@ #endif /* HAVE_POLL_H */ #endif /* HAVE_POLL */ -#ifdef __STDC__ +#if STDC_HEADERS #include #else #include @@ -300,7 +298,16 @@ #endif #if CBDATA_DEBUG -#define cbdataAdd(a,b) cbdataAddDbg(a,b,__FILE__,__LINE__) +#define cbdataAdd(a,b,c) cbdataAddDbg(a,b,c,__FILE__,__LINE__) +#endif + +#if USE_LEAKFINDER +#define leakAdd(p) leakAddFL(p,__FILE__,__LINE__) +#define leakTouch(p) leakTouchFL(p,__FILE__,__LINE__) +#else +#define leakAdd(p) p +#define leakTouch(p) p +#define leakFree(p) p #endif #if defined(_SQUID_NEXT_) && !defined(S_ISDIR) @@ -362,11 +369,21 @@ /* * Squid source files should not call these functions directly */ +#ifndef malloc #define malloc + +#endif +#ifndef free #define free + +#endif +#ifndef calloc #define calloc + +#endif +#ifndef sprintf #define sprintf + +#endif +#ifndef strdup #define strdup + +#endif #if SQUID_SNMP extern struct snmp_mib_tree *Mib; Index: squid/src/ssl.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/ssl.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/ssl.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/ssl.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: ssl.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: ssl.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 26 Secure Sockets Layer Proxy * AUTHOR: Duane Wessels @@ -40,13 +40,16 @@ char *host; /* either request->host or proxy host */ u_short port; request_t *request; + FwdServer *servers; struct { int fd; int len; char *buf; } client, server; size_t *size_ptr; /* pointer to size in an ConnStateData for logging */ - int proxying; +#if DELAY_POOLS + delay_id delay_id; +#endif } SslStateData; static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n"; @@ -61,7 +64,6 @@ static PF sslWriteClient; static PF sslWriteServer; static PSC sslPeerSelectComplete; -static PSC sslPeerSelectFail; static void sslStateFree(SslStateData * sslState); static void sslConnected(int fd, void *); static void sslProxyConnected(int fd, void *); @@ -102,9 +104,13 @@ safe_free(sslState->server.buf); safe_free(sslState->client.buf); safe_free(sslState->url); + fwdServersFree(&sslState->servers); sslState->host = NULL; requestUnlink(sslState->request); sslState->request = NULL; +#if DELAY_POOLS + delayUnregisterDelayIdPtr(&sslState->delay_id); +#endif cbdataFree(sslState); } @@ -112,8 +118,8 @@ static int sslDeferServerRead(int fdnotused, void *data) { - request_t *r = data; - return delayBytesWanted(r->delay_id, 0, 1) == 0; + SslStateData *s = data; + return delayBytesWanted(s->delay_id, 0, 1) == 0; } #endif @@ -155,7 +161,7 @@ * no data flowing in the other direction. Hence the argument of * 1 as min. */ - read_sz = delayBytesWanted(sslState->request->delay_id, 1, read_sz); + read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz); #endif if (sslState->server.len < read_sz) { /* Have room to read more */ @@ -184,7 +190,7 @@ fd, read_sz, sslState->server.len); errno = 0; #if DELAY_POOLS - read_sz = delayBytesWanted(sslState->request->delay_id, 1, read_sz); + read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz); #endif Counter.syscalls.sock.reads++; len = read(fd, sslState->server.buf + sslState->server.len, read_sz); @@ -192,7 +198,7 @@ if (len > 0) { fd_bytes(fd, len, FD_READ); #if DELAY_POOLS - delayBytesIn(sslState->request->delay_id, len); + delayBytesIn(sslState->delay_id, len); #endif kb_incr(&Counter.server.all.kbytes_in, len); kb_incr(&Counter.server.other.kbytes_in, len); @@ -383,7 +389,7 @@ err->callback_data = sslState; errorSend(sslState->client.fd, err); } else { - if (sslState->proxying) + if (sslState->servers->peer) sslProxyConnected(sslState->server.fd, sslState); else sslConnected(sslState->server.fd, sslState); @@ -392,7 +398,7 @@ sslTimeout, sslState); #if DELAY_POOLS - commSetDefer(sslState->server.fd, sslDeferServerRead, sslState->request); + commSetDefer(sslState->server.fd, sslDeferServerRead, sslState); #endif } } @@ -424,7 +430,11 @@ return; } sslState = xcalloc(1, sizeof(SslStateData)); - cbdataAdd(sslState, MEM_NONE); + cbdataAdd(sslState, cbdataXfree, 0); +#if DELAY_POOLS + sslState->delay_id = delayClient(request); + delayRegisterDelayIdPtr(&sslState->delay_id); +#endif sslState->url = xstrdup(url); sslState->request = requestLink(request); sslState->size_ptr = size_ptr; @@ -449,7 +459,6 @@ peerSelect(request, NULL, sslPeerSelectComplete, - sslPeerSelectFail, sslState); /* * Disable the client read handler until peer selection is complete @@ -493,38 +502,44 @@ } static void -sslPeerSelectComplete(peer * p, void *data) +sslPeerSelectComplete(FwdServer * fs, void *data) { SslStateData *sslState = data; request_t *request = sslState->request; peer *g = NULL; - sslState->proxying = p ? 1 : 0; - sslState->host = p ? p->host : request->host; - if (p == NULL) { + if (fs == NULL) { + ErrorState *err; + err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE); + err->request = requestLink(sslState->request); + err->callback = sslErrorComplete; + err->callback_data = sslState; + errorSend(sslState->client.fd, err); + return; + } + sslState->servers = fs; + sslState->host = fs->peer ? fs->peer->host : request->host; + if (fs->peer == NULL) { sslState->port = request->port; - } else if (p->http_port != 0) { - sslState->port = p->http_port; - } else if ((g = peerFindByName(p->host))) { + } else if (fs->peer->http_port != 0) { + sslState->port = fs->peer->http_port; + } else if ((g = peerFindByName(fs->peer->host))) { sslState->port = g->http_port; } else { sslState->port = CACHE_HTTP_PORT; } +#if DELAY_POOLS + /* no point using the delayIsNoDelay stuff since ssl is nice and simple */ + if (g && g->options.no_delay && sslState->delay_id) { + delayUnregisterDelayIdPtr(&sslState->delay_id); + sslState->delay_id = 0; + } +#endif + hierarchyNote(&sslState->request->hier, + fs->peer ? fs->code : DIRECT, + sslState->host); commConnectStart(sslState->server.fd, sslState->host, sslState->port, sslConnectDone, sslState); } - -static void -sslPeerSelectFail(peer * peernotused, void *data) -{ - SslStateData *sslState = data; - ErrorState *err; - err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE); - err->request = requestLink(sslState->request); - err->callback = sslErrorComplete; - err->callback_data = sslState; - errorSend(sslState->client.fd, err); - -} Index: squid/src/stat.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/stat.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/stat.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/stat.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: stat.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: stat.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 18 Cache Manager Statistics * AUTHOR: Harvest Derived @@ -76,8 +76,7 @@ static OBJH statAvg60min; static OBJH statUtilization; static OBJH statCountersHistograms; -static double statRequestHitRatio(int minutes); -static double statByteHitRatio(int minutes); +static OBJH statClientRequests; #ifdef XMALLOC_STATISTICS static void info_get_mallstat(int, int, StoreEntry *); @@ -221,12 +220,16 @@ strcat(buf, "DISPATCHED,"); if (EBIT_TEST(flags, KEY_PRIVATE)) strcat(buf, "PRIVATE,"); + if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT)) + strcat(buf, "FWD_HDR_WAIT,"); if (EBIT_TEST(flags, ENTRY_NEGCACHED)) strcat(buf, "NEGCACHED,"); if (EBIT_TEST(flags, ENTRY_VALIDATED)) strcat(buf, "VALIDATED,"); if (EBIT_TEST(flags, ENTRY_BAD_LENGTH)) strcat(buf, "BAD_LENGTH,"); + if (EBIT_TEST(flags, ENTRY_ABORTED)) + strcat(buf, "ABORTED,"); if ((t = strrchr(buf, ','))) *t = '\0'; return buf; @@ -273,7 +276,7 @@ for (i = 0, sc = &mem->clients[i]; sc != NULL; sc = sc->next, i++) { if (sc->callback_data == NULL) continue; - storeAppendPrintf(s, "\tClient #%d\n", i); + storeAppendPrintf(s, "\tClient #%d, %p\n", i, sc->callback_data); storeAppendPrintf(s, "\t\tcopy_offset: %d\n", (int) sc->copy_offset); storeAppendPrintf(s, "\t\tseen_offset: %d\n", @@ -308,7 +311,7 @@ storeUnlockObject(state->sentry); cbdataFree(state); return; - } else if (state->sentry->store_status == STORE_ABORTED) { + } else if (EBIT_TEST(state->sentry->flags, ENTRY_ABORTED)) { storeUnlockObject(state->sentry); cbdataFree(state); return; @@ -338,7 +341,7 @@ state->sentry = sentry; state->filter = filter; storeLockObject(sentry); - cbdataAdd(state, MEM_NONE); + cbdataAdd(state, cbdataXfree, 0); eventAdd("statObjects", statObjects, state, 0.0, 1); } @@ -404,7 +407,7 @@ int i; fde *f; storeAppendPrintf(sentry, "Active file descriptors:\n"); - storeAppendPrintf(sentry, "%-4s %-6s %-4s %-7s %-7s %-21s %s\n", + storeAppendPrintf(sentry, "%-4s %-6s %-4s %-7s* %-7s* %-21s %s\n", "File", "Type", "Tout", @@ -412,17 +415,19 @@ "Nwrite", "Remote Address", "Description"); - storeAppendPrintf(sentry, "---- ------ ---- ------- ------- --------------------- ------------------------------\n"); + storeAppendPrintf(sentry, "---- ------ ---- -------- -------- --------------------- ------------------------------\n"); for (i = 0; i < Squid_MaxFD; i++) { f = &fd_table[i]; - if (!f->open) + if (!f->flags.open) continue; - storeAppendPrintf(sentry, "%4d %-6.6s %4d %7d %7d %-21s %s\n", + storeAppendPrintf(sentry, "%4d %-6.6s %4d %7d%c %7d%c %-21s %s\n", i, fdTypeStr[f->type], f->timeout_handler ? (int) (f->timeout - squid_curtime) / 60 : 0, f->bytes_read, + f->read_handler ? '*' : ' ', f->bytes_written, + f->write_handler ? '*' : ' ', fdRemoteAddr(f), f->desc); } @@ -436,7 +441,7 @@ double runtime; #if HAVE_MSTATS && HAVE_GNUMALLOC_H struct mstats ms; -#elif HAVE_MALLINFO +#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO struct mallinfo mp; int t; #endif @@ -538,7 +543,7 @@ ms.bytes_total >> 10); storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n", ms.bytes_free >> 10, percent(ms.bytes_free, ms.bytes_total)); -#elif HAVE_MALLINFO +#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO mp = mallinfo(); storeAppendPrintf(sentry, "Memory usage for %s via mallinfo():\n", appname); @@ -584,12 +589,14 @@ Biggest_FD); storeAppendPrintf(sentry, "\tNumber of file desc currently in use: %4d\n", Number_FD); + storeAppendPrintf(sentry, "\tFiles queued for open: %4d\n", + Opening_FD); storeAppendPrintf(sentry, "\tAvailable number of file descriptors: %4d\n", - Squid_MaxFD - Number_FD); + fdNFree()); storeAppendPrintf(sentry, "\tReserved number of file descriptors: %4d\n", RESERVED_FD); - storeAppendPrintf(sentry, "\tDisk files open: %4d\n", - open_disk_fd); + storeAppendPrintf(sentry, "\tStore Disk files open: %4d\n", + store_open_disk_fd); storeAppendPrintf(sentry, "Internal Data Structures:\n"); storeAppendPrintf(sentry, "\t%6d StoreEntries\n", @@ -857,6 +864,11 @@ cachemgrRegister("histograms", "Full Histogram Counts", statCountersHistograms, 0, 1); + ClientActiveRequests.head = NULL; + ClientActiveRequests.tail = NULL; + cachemgrRegister("active_requests", + "Client-side Active Requests", + statClientRequests, 0, 1); } static void @@ -866,7 +878,7 @@ StatCounters *p = &CountHist[1]; StatCounters *c = &Counter; struct rusage rusage; - eventAdd("statAvgTick", statAvgTick, NULL, COUNT_INTERVAL, 1); + eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1); squid_getrusage(&rusage); c->page_faults = rusage_pagefaults(&rusage); c->cputime = rusage_cputime(&rusage); @@ -1143,27 +1155,10 @@ /* per-peer */ storeAppendPrintf(sentry, "\nPer-peer statistics:\n"); for (peer = getFirstPeer(); peer; peer = getNextPeer(peer)) { - cacheDigestGuessStatsReport(&peer->digest.stats.guess, sentry, peer->host); - storeAppendPrintf(sentry, "peer.msgs_sent = %d\n", - peer->digest.stats.msgs_sent); - storeAppendPrintf(sentry, "peer.msgs_recv = %d\n", - peer->digest.stats.msgs_recv); - storeAppendPrintf(sentry, "peer.kbytes_sent = %d\n", - (int) peer->digest.stats.kbytes_sent.kb); - storeAppendPrintf(sentry, "peer.kbytes_recv = %d\n", - (int) peer->digest.stats.kbytes_recv.kb); - storeAppendPrintf(sentry, "peer.local_memory = %d\n", - peer->digest.cd ? peer->digest.cd->mask_size / 1024 : 0); - storeAppendPrintf(sentry, "digest state: inited: %d, disabled: %d usable: %d requested: %d\n", - 0 < peer->digest.flags.inited, - 0 < peer->digest.flags.disabled, - 0 < peer->digest.flags.usable, - 0 < peer->digest.flags.requested - ); - if (peer->digest.cd) - cacheDigestReport(peer->digest.cd, peer->host, sentry); + if (peer->digest) + peerDigestStatsReport(peer->digest, sentry); else - storeAppendPrintf(sentry, "no cache digest from peer %s\n", peer->host); + storeAppendPrintf(sentry, "\nNo peer digest from %s\n", peer->host); storeAppendPrintf(sentry, "\n"); } @@ -1278,7 +1273,7 @@ tvSubDsec(CountHist[minutes].timestamp, CountHist[0].timestamp)); } -static double +extern double statRequestHitRatio(int minutes) { assert(minutes < N_COUNT_HIST); @@ -1288,7 +1283,7 @@ CountHist[minutes].client_http.requests); } -static double +extern double statByteHitRatio(int minutes) { size_t s; @@ -1303,6 +1298,54 @@ return (-1.0 * dpercent(s - c, c)); } +static void +statClientRequests(StoreEntry * s) +{ + dlink_node *i; + clientHttpRequest *http; + ConnStateData *conn; + StoreEntry *e; + int fd; + for (i = ClientActiveRequests.head; i; i = i->next) { + http = i->data; + assert(http); + conn = http->conn; + storeAppendPrintf(s, "Connection: %p\n", conn); + if (conn) { + fd = conn->fd; + storeAppendPrintf(s, "\tFD %d, read %d, wrote %d\n", fd, + fd_table[fd].bytes_read, fd_table[fd].bytes_written); + storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc); + storeAppendPrintf(s, "\tin: buf %p, offset %d, size %d\n", + conn->in.buf, conn->in.offset, conn->in.size); + storeAppendPrintf(s, "\tpeer: %s:%d\n", + inet_ntoa(conn->peer.sin_addr), + ntohs(conn->peer.sin_port)); + storeAppendPrintf(s, "\tme: %s:%d\n", + inet_ntoa(conn->me.sin_addr), + ntohs(conn->me.sin_port)); + storeAppendPrintf(s, "\tnrequests: %d\n", + conn->nrequests); + storeAppendPrintf(s, "\tpersistent: %d\n", + conn->persistent); + storeAppendPrintf(s, "\tdefer: n %d, until %d\n", + conn->defer.n, conn->defer.until); + } + storeAppendPrintf(s, "uri %s\n", http->uri); + storeAppendPrintf(s, "out.offset %d, out.size %d\n", + http->out.offset, http->out.size); + storeAppendPrintf(s, "req_sz %d\n", http->req_sz); + e = http->entry; + storeAppendPrintf(s, "entry %p/%s\n", e, e ? storeKeyText(e->key) : "N/A"); + e = http->old_entry; + storeAppendPrintf(s, "old_entry %p/%s\n", e, e ? storeKeyText(e->key) : "N/A"); + storeAppendPrintf(s, "start %d.%06d (%f seconds ago)\n", http->start.tv_sec, + http->start.tv_usec, + tvSubDsec(http->start, current_time)); + storeAppendPrintf(s, "\n"); + } +} + #if STAT_GRAPHS /* * urgh, i don't like these, but they do cut the amount of code down immensely Index: squid/src/stmem.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/stmem.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/stmem.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/stmem.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: stmem.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: stmem.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 19 Store Memory Primitives * AUTHOR: Harvest Derived @@ -41,7 +41,7 @@ mem_node *p; while ((p = mem->head)) { mem->head = p->next; - memFree(MEM_STMEM_BUF, p->data); + memFree(p->data, MEM_STMEM_BUF); store_mem_size -= SM_PAGE_SIZE; safe_free(p); } @@ -65,7 +65,7 @@ lastp = p; p = p->next; current_offset += lastp->len; - memFree(MEM_STMEM_BUF, lastp->data); + memFree(lastp->data, MEM_STMEM_BUF); store_mem_size -= SM_PAGE_SIZE; safe_free(lastp); } Index: squid/src/store.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/store.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/store.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/store.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: store.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: store.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 20 Storage Manager * AUTHOR: Harvest Derived @@ -49,15 +49,13 @@ { "PING_NONE", "PING_WAITING", - "PING_TIMEOUT", "PING_DONE" }; const char *storeStatusStr[] = { "STORE_OK", - "STORE_PENDING", - "STORE_ABORTED" + "STORE_PENDING" }; const char *swapStatusStr[] = @@ -95,8 +93,7 @@ * local variables */ static dlink_list inmem_list; -static int store_pages_high = 0; -static int store_pages_low = 0; +static int store_pages_max = 0; static int store_swap_high = 0; static int store_swap_low = 0; static int store_swap_mid = 0; @@ -157,7 +154,7 @@ ctx_exit(ctx); /* must exit before we free mem->url */ safe_free(mem->url); safe_free(mem->log_url); - memFree(MEM_MEMOBJECT, mem); + memFree(mem, MEM_MEMOBJECT); } static void @@ -170,7 +167,7 @@ destroy_MemObject(e); storeHashDelete(e); assert(e->key == NULL); - memFree(MEM_STOREENTRY, e); + memFree(e, MEM_STOREENTRY); } /* ----- INTERFACE BETWEEN STORAGE MANAGER AND HASH TABLE FUNCTIONS --------- */ @@ -250,10 +247,8 @@ storeKeyText(e->key), e->lock_count); if (e->lock_count) return (int) e->lock_count; - if (e->store_status == STORE_PENDING) { - assert(!EBIT_TEST(e->flags, ENTRY_DISPATCHED)); + if (e->store_status == STORE_PENDING) EBIT_SET(e->flags, RELEASE_REQUEST); - } assert(storePendingNClients(e) == 0); if (EBIT_TEST(e->flags, RELEASE_REQUEST)) storeRelease(e); @@ -283,10 +278,7 @@ StoreEntry * storeGetPublic(const char *uri, const method_t method) { - StoreEntry *e = storeGet(storeKeyPublic(uri, method)); - if (e == NULL && squid_curtime < 920000000) - e = storeGet(storeKeyPublicOld(uri, method)); - return e; + return storeGet(storeKeyPublic(uri, method)); } static int @@ -387,9 +379,6 @@ e->timestamp = 0; /* set in storeTimestampsSet() */ e->ping_status = PING_NONE; EBIT_SET(e->flags, ENTRY_VALIDATED); -#ifdef PPNR_WIP - EBIT_SET(e->flags, ENTRY_FWD_HDR_WAIT); -#endif /* PPNR_WIP */ return e; } @@ -408,6 +397,7 @@ MemObject *mem = e->mem_obj; assert(mem != NULL); assert(len >= 0); + assert(e->store_status == STORE_PENDING); if (len) { debug(20, 5) ("storeAppend: appending %d bytes for '%s'\n", len, @@ -428,17 +418,18 @@ #endif } -#ifdef __STDC__ void +#if STDC_HEADERS storeAppendPrintf(StoreEntry * e, const char *fmt,...) -{ - va_list args; - va_start(args, fmt); #else -void storeAppendPrintf(va_alist) va_dcl +#endif { +#if STDC_HEADERS + va_list args; + va_start(args, fmt); +#else va_list args; StoreEntry *e = NULL; const char *fmt = NULL; @@ -470,6 +461,7 @@ int too_big; int private_key; int too_many_open_files; + int too_many_open_fds; int lru_age_too_low; } no; struct { @@ -482,7 +474,7 @@ { if (Config.max_open_disk_fds == 0) return 0; - if (open_disk_fd > Config.max_open_disk_fds) + if (store_open_disk_fd > Config.max_open_disk_fds) return 1; return 0; } @@ -515,9 +507,19 @@ } else if (EBIT_TEST(e->flags, KEY_PRIVATE)) { debug(20, 3) ("storeCheckCachable: NO: private key\n"); store_check_cachable_hist.no.private_key++; + } else if (e->swap_status != SWAPOUT_NONE) { + /* + * here we checked the swap_status because the remaining + * cases are only relevant only if we haven't started swapping + * out the object yet. + */ + return 1; } else if (storeTooManyDiskFilesOpen()) { debug(20, 2) ("storeCheckCachable: NO: too many disk files open\n"); store_check_cachable_hist.no.too_many_open_files++; + } else if (fdNFree() < RESERVED_FD) { + debug(20, 2) ("storeCheckCachable: NO: too many FD's open\n"); + store_check_cachable_hist.no.too_many_open_fds++; } else if (storeExpiredReferenceAge() < 300) { debug(20, 2) ("storeCheckCachable: NO: LRU Age = %d\n", storeExpiredReferenceAge()); @@ -534,6 +536,8 @@ static void storeCheckCachableStats(StoreEntry * sentry) { + storeAppendPrintf(sentry, "Category\t Count\n"); + storeAppendPrintf(sentry, "no.non_get\t%d\n", store_check_cachable_hist.no.non_get); storeAppendPrintf(sentry, "no.not_entry_cachable\t%d\n", @@ -550,6 +554,8 @@ store_check_cachable_hist.no.private_key); storeAppendPrintf(sentry, "no.too_many_open_files\t%d\n", store_check_cachable_hist.no.too_many_open_files); + storeAppendPrintf(sentry, "no.too_many_open_fds\t%d\n", + store_check_cachable_hist.no.too_many_open_fds); storeAppendPrintf(sentry, "no.lru_age_too_low\t%d\n", store_check_cachable_hist.no.lru_age_too_low); storeAppendPrintf(sentry, "yes.default\t%d\n", @@ -561,7 +567,15 @@ storeComplete(StoreEntry * e) { debug(20, 3) ("storeComplete: '%s'\n", storeKeyText(e->key)); - assert(e->store_status == STORE_PENDING); + if (e->store_status != STORE_PENDING) { + /* + * if we're not STORE_PENDING, then probably we got aborted + * and there should be NO clients on this entry + */ + assert(EBIT_TEST(e->flags, ENTRY_ABORTED)); + assert(e->mem_obj->nclients == 0); + return; + } e->mem_obj->object_sz = e->mem_obj->inmem_hi; e->store_status = STORE_OK; assert(e->mem_status == NOT_IN_MEMORY); @@ -577,49 +591,40 @@ storeCheckSwapOut(e); } -#ifdef PPNR_WIP -void -storePPNR(StoreEntry * e) -{ - assert(EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)); - EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT); -} - -#endif /* PPNR_WIP */ - /* * Someone wants to abort this transfer. Set the reason in the * request structure, call the server-side callback and mark the * entry for releasing */ void -storeAbort(StoreEntry * e, int cbflag) +storeAbort(StoreEntry * e) { MemObject *mem = e->mem_obj; - STABH *callback; - void *data; assert(e->store_status == STORE_PENDING); assert(mem != NULL); debug(20, 6) ("storeAbort: %s\n", storeKeyText(e->key)); storeLockObject(e); /* lock while aborting */ storeNegativeCache(e); storeReleaseRequest(e); - e->store_status = STORE_ABORTED; + EBIT_SET(e->flags, ENTRY_ABORTED); storeSetMemStatus(e, NOT_IN_MEMORY); /* No DISK swap for negative cached object */ e->swap_status = SWAPOUT_NONE; + e->store_status = STORE_OK; /* * We assign an object length here. The only other place we assign * the object length is in storeComplete() */ mem->object_sz = mem->inmem_hi; /* Notify the server side */ - if (cbflag && mem->abort.callback) { - callback = mem->abort.callback; - data = mem->abort.data; + if (mem->abort.callback) { + eventAdd("mem->abort.callback", + mem->abort.callback, + mem->abort.data, + 0.0, + 0); mem->abort.callback = NULL; mem->abort.data = NULL; - callback(data); } /* Notify the client side */ InvokeHandlers(e); @@ -657,7 +662,7 @@ return; last_check = squid_curtime; pages_needed = (size / SM_PAGE_SIZE) + 1; - if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_high) + if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max) return; if (store_rebuilding) return; @@ -675,7 +680,7 @@ } released++; storePurgeMem(e); - if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_high) + if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max) break; } debug(20, 3) ("storeGetMemSpace stats:\n"); @@ -705,25 +710,21 @@ int expired = 0; int max_scan; int max_remove; + double f; static time_t last_warn_time = 0; /* We can't delete objects while rebuilding swap */ if (store_rebuilding) { eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0, 1); return; - } else if (store_swap_size < store_swap_mid) { - max_scan = 100; - max_remove = 8; - eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0, 1); - } else if (store_swap_size < store_swap_high) { - max_scan = 200; - max_remove = 8; - eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 0.1, 1); } else { - max_scan = 500; - max_remove = 32; - eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 0.0, 1); + f = (double) (store_swap_size - store_swap_low) / (store_swap_high - store_swap_low); + f = f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f; + max_scan = (int) (f * 400.0 + 100.0); + max_remove = (int) (f * 70.0 + 10.0); + eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0 - f, 1); } - debug(20, 3) ("storeMaintainSwapSpace\n"); + debug(20, 3) ("storeMaintainSwapSpace: f=%f, max_scan=%d, max_remove=%d\n", + f, max_scan, max_remove); for (m = store_list.tail; m; m = prev) { prev = m->prev; e = m->data; @@ -919,7 +920,7 @@ store_hash_buckets, store_maintain_rate, store_maintain_rate == 1 ? null_string : "s"); - debug(20, 1) ("Max Mem size: %d KB\n", Config.Mem.maxSize >> 10); + debug(20, 1) ("Max Mem size: %d KB\n", Config.memMaxSize >> 10); debug(20, 1) ("Max Swap size: %d KB\n", Config.Swap.maxSize); } @@ -957,21 +958,12 @@ void storeConfigure(void) { - int store_mem_high = 0; - int store_mem_low = 0; - store_mem_high = (long) (Config.Mem.maxSize / 100) * - Config.Mem.highWaterMark; - store_mem_low = (long) (Config.Mem.maxSize / 100) * - Config.Mem.lowWaterMark; - store_swap_high = (long) (((float) Config.Swap.maxSize * (float) Config.Swap.highWaterMark) / (float) 100); store_swap_low = (long) (((float) Config.Swap.maxSize * (float) Config.Swap.lowWaterMark) / (float) 100); store_swap_mid = (store_swap_high >> 1) + (store_swap_low >> 1); - - store_pages_high = store_mem_high / SM_PAGE_SIZE; - store_pages_low = store_mem_low / SM_PAGE_SIZE; + store_pages_max = Config.memMaxSize / SM_PAGE_SIZE; } static int @@ -1063,7 +1055,7 @@ if (EBIT_TEST(e->flags, ENTRY_NEGCACHED)) if (e->expires <= squid_curtime) return 0; - if (e->store_status == STORE_ABORTED) + if (EBIT_TEST(e->flags, ENTRY_ABORTED)) return 0; return 1; } @@ -1240,3 +1232,15 @@ return NULL; return e->mem_obj->reply; } + +void +storeEntryReset(StoreEntry * e) +{ + MemObject *mem = e->mem_obj; + debug(20, 3) ("storeEntryReset: %s\n", storeUrl(e)); + assert(mem->swapout.fd == -1); + stmemFree(&mem->data_hdr); + mem->inmem_hi = mem->inmem_lo = 0; + httpReplyDestroy(mem->reply); + mem->reply = httpReplyCreate(); +} Index: squid/src/store_clean.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/store_clean.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/store_clean.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/store_clean.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,7 +1,7 @@ /* - * $Id: store_clean.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: store_clean.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 36 Cache Directory Cleanup * AUTHOR: Duane Wessels @@ -54,6 +54,9 @@ struct dirent *de = NULL; LOCAL_ARRAY(char, p1, MAXPATHLEN + 1); LOCAL_ARRAY(char, p2, MAXPATHLEN + 1); +#if USE_TRUNCATE_NOT_UNLINK + struct stat sb; +#endif int files[20]; int swapfileno; int fn; /* same as swapfileno, but with dirn bits set */ @@ -93,6 +96,11 @@ if (storeDirMapBitTest(fn)) if (storeFilenoBelongsHere(fn, D0, D1, D2)) continue; +#if USE_TRUNCATE_NOT_UNLINK + if (!stat(de->d_name, &sb)) + if (sb.st_size == 0) + continue; +#endif files[k++] = swapfileno; } closedir(dp); @@ -105,7 +113,11 @@ for (n = 0; n < k; n++) { debug(36, 3) ("storeDirClean: Cleaning file %08X\n", files[n]); snprintf(p2, MAXPATHLEN + 1, "%s/%08X", p1, files[n]); +#if USE_TRUNCATE_NOT_UNLINK + truncate(p2, 0); +#else safeunlink(p2, 0); +#endif Counter.swap_files_cleaned++; } debug(36, 3) ("Cleaned %d unused files from %s\n", k, p1); Index: squid/src/store_client.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/store_client.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/store_client.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/store_client.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: store_client.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: store_client.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 20 Storage Manager Client-Side Interface * AUTHOR: Duane Wessels @@ -47,6 +47,8 @@ static void storeClientFileRead(store_client * sc); static EVH storeClientCopyEvent; static store_client_t storeClientType(StoreEntry *); +static int CheckQuickAbort2(StoreEntry * entry); +static void CheckQuickAbort(StoreEntry * entry); /* check if there is any client waiting for this object at all */ /* return 1 if there is at least one client */ @@ -79,9 +81,9 @@ MemObject *mem = e->mem_obj; if (mem->inmem_lo) return STORE_DISK_CLIENT; - if (e->store_status == STORE_ABORTED) { + if (EBIT_TEST(e->flags, ENTRY_ABORTED)) { /* I don't think we should be adding clients to aborted entries */ - debug(20, 1) ("storeClientType: adding to STORE_ABORTED entry\n"); + debug(20, 1) ("storeClientType: adding to ENTRY_ABORTED entry\n"); return STORE_MEM_CLIENT; } if (e->store_status == STORE_OK) { @@ -116,7 +118,7 @@ return; mem->nclients++; sc = memAllocate(MEM_STORE_CLIENT); - cbdataAdd(sc, MEM_STORE_CLIENT); /* sc is callback_data for file_read */ + cbdataAdd(sc, memFree, MEM_STORE_CLIENT); /* sc is callback_data for file_read */ sc->callback_data = data; sc->seen_offset = 0; sc->copy_offset = 0; @@ -130,6 +132,9 @@ assert(e->swap_file_number > -1 || storeSwapOutAble(e)); for (T = &mem->clients; *T; T = &(*T)->next); *T = sc; +#if DELAY_POOLS + sc->delay_id = 0; +#endif } static void @@ -154,7 +159,7 @@ void *data) { store_client *sc; - assert(e->store_status != STORE_ABORTED); + assert(!EBIT_TEST(e->flags, ENTRY_ABORTED)); debug(20, 3) ("storeClientCopy: %s, seen %d, want %d, size %d, cb %p, cbdata %p\n", storeKeyText(e->key), (int) seen_offset, @@ -177,7 +182,7 @@ /* * This function is used below to decide if we have any more data to * send to the client. If the store_status is STORE_PENDING, then we - * do have more data to send. If its STORE_OK or STORE_ABORTED, then + * do have more data to send. If its STORE_OK, then * we continue checking. If the object length is negative, then we * don't know the real length and must open the swap file to find out. * If the length is >= 0, then we compare it to the requested copy @@ -204,10 +209,10 @@ size_t sz; if (sc->flags.copy_event_pending) return; -#ifdef PPNR_WIP - if (EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) + if (EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) { + debug(20, 5) ("storeClientCopy2: returning because ENTRY_FWD_HDR_WAIT set\n"); return; -#endif /* PPNR_WIP */ + } if (sc->flags.store_copying) { sc->flags.copy_event_pending = 1; debug(20, 3) ("storeClientCopy2: Queueing storeClientCopyEvent()\n"); @@ -219,7 +224,7 @@ debug(20, 3) ("storeClientCopy2: %s\n", storeKeyText(e->key)); assert(callback != NULL); /* - * We used to check for STORE_ABORTED here. But there were some + * We used to check for ENTRY_ABORTED here. But there were some * problems. For example, we might have a slow client (or two) and * the server-side is reading far ahead and swapping to disk. Even * if the server-side aborts, we want to give the client(s) @@ -260,8 +265,11 @@ debug(20, 3) ("storeClientCopy2: Need to open swap in file\n"); assert(sc->type == STORE_DISK_CLIENT); /* gotta open the swapin file */ - /* assert(sc->copy_offset == 0); */ - if (!sc->flags.disk_io_pending) { + if (storeTooManyDiskFilesOpen()) { + /* yuck -- this causes a TCP_SWAPFAIL_MISS on the client side */ + sc->callback = NULL; + callback(sc->callback_data, sc->copy_buf, -1); + } else if (!sc->flags.disk_io_pending) { sc->flags.disk_io_pending = 1; storeSwapInStart(e, storeClientFileOpened, sc); } else { @@ -445,9 +453,8 @@ if (e->store_status == STORE_OK && e->swap_status != SWAPOUT_DONE) storeCheckSwapOut(e); if (sc->swapin_fd > -1) { - commSetSelect(sc->swapin_fd, COMM_SELECT_READ, NULL, NULL, 0); file_close(sc->swapin_fd); - /* XXX this probably leaks file_read handler structures */ + store_open_disk_fd--; } #if USE_ASYNC_IO else @@ -460,7 +467,13 @@ sc->callback = NULL; callback(sc->callback_data, sc->copy_buf, -1); } +#if DELAY_POOLS + delayUnregisterDelayIdPtr(&sc->delay_id); +#endif cbdataFree(sc); + assert(e->lock_count > 0); + if (mem->nclients == 0) + CheckQuickAbort(e); return 1; } @@ -513,3 +526,69 @@ debug(20, 3) ("storePendingNClients: returning %d\n", npend); return npend; } + +/* return 1 if the request should be aborted */ +static int +CheckQuickAbort2(StoreEntry * entry) +{ + int curlen; + int minlen; + int expectlen; + MemObject *mem = entry->mem_obj; + assert(mem); + debug(20, 3) ("CheckQuickAbort2: entry=%p, mem=%p\n", entry, mem); + if (mem->request && !mem->request->flags.cachable) { + debug(20, 3) ("CheckQuickAbort2: YES !mem->request->flags.cachable\n"); + return 1; + } + if (EBIT_TEST(entry->flags, KEY_PRIVATE)) { + debug(20, 3) ("CheckQuickAbort2: YES KEY_PRIVATE\n"); + return 1; + } + expectlen = mem->reply->content_length + mem->reply->hdr_sz; + curlen = (int) mem->inmem_hi; + minlen = (int) Config.quickAbort.min << 10; + if (minlen < 0) { + debug(20, 3) ("CheckQuickAbort2: NO disabled\n"); + return 0; + } + if (curlen > expectlen) { + debug(20, 3) ("CheckQuickAbort2: YES bad content length\n"); + return 1; + } + if ((expectlen - curlen) < minlen) { + debug(20, 3) ("CheckQuickAbort2: NO only little more left\n"); + return 0; + } + if ((expectlen - curlen) > (Config.quickAbort.max << 10)) { + debug(20, 3) ("CheckQuickAbort2: YES too much left to go\n"); + return 1; + } + if (expectlen < 100) { + debug(20, 3) ("CheckQuickAbort2: NO avoid FPE\n"); + return 0; + } + if ((curlen / (expectlen / 100)) > Config.quickAbort.pct) { + debug(20, 3) ("CheckQuickAbort2: NO past point of no return\n"); + return 0; + } + debug(20, 3) ("CheckQuickAbort2: YES default, returning 1\n"); + return 1; +} + +static void +CheckQuickAbort(StoreEntry * entry) +{ + if (entry == NULL) + return; + if (storePendingNClients(entry) > 0) + return; + if (entry->store_status != STORE_PENDING) + return; + if (EBIT_TEST(entry->flags, ENTRY_SPECIAL)) + return; + if (CheckQuickAbort2(entry) == 0) + return; + Counter.aborted_requests++; + storeAbort(entry); +} Index: squid/src/store_digest.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/store_digest.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/store_digest.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/store_digest.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: store_digest.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: store_digest.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 71 Store Digest Manager * AUTHOR: Alex Rousskov @@ -335,12 +335,12 @@ } debug(71, 2) ("storeDigestRewrite: start rewrite #%d\n", sd_state.rewrite_count + 1); /* make new store entry */ - url = internalLocalUri("/squid-internal-periodic/", StoreDigestUrlPath); + url = internalLocalUri("/squid-internal-periodic/", StoreDigestFileName); flags = null_request_flags; flags.cachable = 1; sd_state.rewrite_lock = e = storeCreateEntry(url, url, flags, METHOD_GET); assert(sd_state.rewrite_lock); - cbdataAdd(sd_state.rewrite_lock, MEM_DONTFREE); + cbdataAdd(sd_state.rewrite_lock, NULL, 0); debug(71, 3) ("storeDigestRewrite: url: %s key: %s\n", url, storeKeyText(e->key)); e->mem_obj->request = requestLink(urlParse(METHOD_GET, url)); /* wait for rebuild (if any) to finish */ @@ -367,7 +367,8 @@ httpReplySetHeaders(e->mem_obj->reply, 1.0, 200, "Cache Digest OK", "application/cache-digest", store_digest->mask_size + sizeof(sd_state.cblock), squid_curtime, squid_curtime + StoreDigestRewritePeriod); - debug(71, 3) ("storeDigestRewrite: entry expires on %s\n", mkrfc1123(e->mem_obj->reply->expires)); + debug(71, 3) ("storeDigestRewrite: entry expires on %d (%+d)\n", + e->mem_obj->reply->expires, e->mem_obj->reply->expires - squid_curtime); storeBuffer(e); httpReplySwapOut(e->mem_obj->reply, e); storeDigestCBlockSwapOut(e); @@ -382,8 +383,8 @@ assert(e == sd_state.rewrite_lock); storeComplete(e); storeTimestampsSet(e); - debug(71, 2) ("storeDigestRewriteFinish: digest expires on %s (%d)\n", - mkrfc1123(e->expires), e->expires); + debug(71, 2) ("storeDigestRewriteFinish: digest expires at %d (%+d)\n", + e->expires, e->expires - squid_curtime); /* is this the write order? @?@ */ requestUnlink(e->mem_obj->request); e->mem_obj->request = NULL; Index: squid/src/store_dir.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/store_dir.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/store_dir.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/store_dir.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: store_dir.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: store_dir.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 47 Store Directory Routines * AUTHOR: Duane Wessels @@ -283,7 +283,7 @@ diru[i] = 1.1; SD = &Config.cacheSwap.swapDirs[i]; SD->flags.selected = 0; - if (SD->read_only) + if (SD->flags.read_only) continue; u = (double) SD->cur_size / SD->max_size; if (u > high) @@ -545,6 +545,12 @@ SwapDir *SD = &Config.cacheSwap.swapDirs[dirn]; int fd; file_close(SD->swaplog_fd); +#ifdef _SQUID_OS2_ + if (unlink(swaplog_path) < 0) { + debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror()); + fatal("storeDirCloseTmpSwapLog: unlink failed"); + } +#endif if (rename(new_path, swaplog_path) < 0) { debug(50, 0) ("%s,%s: %s\n", new_path, swaplog_path, xstrerror()); fatal("storeDirCloseTmpSwapLog: rename failed"); @@ -621,6 +627,8 @@ storeAppendPrintf(sentry, "Flags:"); if (SD->flags.selected) storeAppendPrintf(sentry, " SELECTED"); + if (SD->flags.read_only) + storeAppendPrintf(sentry, " READ-ONLY"); storeAppendPrintf(sentry, "\n"); } } @@ -767,25 +775,27 @@ } safe_free(outbuf); safe_free(outbufoffset); -#ifdef _SQUID_MSWIN_ /* * You can't rename open files on Microsoft "operating systems" - * so we close before renaming. + * so we have to close before renaming. */ storeDirCloseSwapLogs(); -#endif /* rename */ for (dirn = 0; dirn < N; dirn++) { if (fd[dirn] < 0) continue; +#ifdef _SQUID_OS2_ + file_close(fd[dirn]); + fd[dirn] = -1; + if (unlink(cur[dirn]) < 0) + debug(50, 0) ("storeDirWriteCleanLogs: unlinkd failed: %s, %s\n", + xstrerror(), cur[dirn]); +#endif if (rename(new[dirn], cur[dirn]) < 0) { debug(50, 0) ("storeDirWriteCleanLogs: rename failed: %s, %s -> %s\n", xstrerror(), new[dirn], cur[dirn]); } } -#ifndef _SQUID_MSWIN_ - storeDirCloseSwapLogs(); -#endif if (reopen) storeDirOpenSwapLogs(); stop = squid_curtime; Index: squid/src/store_key_md5.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/store_key_md5.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/store_key_md5.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/store_key_md5.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: store_key_md5.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: store_key_md5.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 20 Storage Manager MD5 Cache Keys * AUTHOR: Duane Wessels @@ -107,21 +107,6 @@ return digest; } -/* - * Compatibility transition period. Remove this after Feb 25, 1998 - */ -const cache_key * -storeKeyPublicOld(const char *url, const method_t method) -{ - static cache_key digest[MD5_DIGEST_CHARS]; - MD5_CTX M; - MD5Init(&M); - MD5Update(&M, (unsigned char *) &method, sizeof(method)); - MD5Update(&M, (unsigned char *) url, strlen(url)); - MD5Final(digest, &M); - return digest; -} - const cache_key * storeKeyPublic(const char *url, const method_t method) { @@ -153,7 +138,7 @@ void storeKeyFree(const cache_key * key) { - memFree(MEM_MD5_DIGEST, (void *) key); + memFree((void *) key, MEM_MD5_DIGEST); } int Index: squid/src/store_rebuild.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/store_rebuild.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/store_rebuild.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/store_rebuild.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: store_rebuild.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: store_rebuild.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 20 Store Rebuild Routines * AUTHOR: Duane Wessels @@ -137,6 +137,7 @@ debug(20, 1) ("storeRebuildFromDirectory: fstat(FD %d): %s\n", fd, xstrerror()); file_close(fd); + store_open_disk_fd--; fd = -1; continue; } @@ -149,12 +150,18 @@ debug(20, 1) ("storeRebuildFromDirectory: read(FD %d): %s\n", fd, xstrerror()); file_close(fd); + store_open_disk_fd--; fd = -1; continue; } file_close(fd); + store_open_disk_fd--; fd = -1; swap_hdr_len = 0; +#if USE_TRUNCATE_NOT_UNLINK + if (sb.st_size == 0) + continue; +#endif tlv_list = storeSwapMetaUnpack(hdr_buf, &swap_hdr_len); if (tlv_list == NULL) { debug(20, 1) ("storeRebuildFromDirectory: failed to get meta data\n"); @@ -485,13 +492,13 @@ if (d->td == NULL) { debug(50, 1) ("storeGetNextFile: opendir: %s: %s\n", d->fullpath, xstrerror()); - break; + } else { + d->entry = readdir(d->td); /* skip . and .. */ + d->entry = readdir(d->td); + if (d->entry == NULL && errno == ENOENT) + debug(20, 1) ("storeGetNextFile: directory does not exist!.\n"); + debug(20, 3) ("storeGetNextFile: Directory %s\n", d->fullpath); } - d->entry = readdir(d->td); /* skip . and .. */ - d->entry = readdir(d->td); - if (d->entry == NULL && errno == ENOENT) - debug(20, 1) ("storeGetNextFile: directory does not exist!.\n"); - debug(20, 3) ("storeGetNextFile: Directory %s\n", d->fullpath); } if (d->td != NULL && (d->entry = readdir(d->td)) != NULL) { d->in_dir++; @@ -518,6 +525,7 @@ if (fd < 0) debug(50, 1) ("storeGetNextFile: %s: %s\n", d->fullfilename, xstrerror()); continue; + store_open_disk_fd++; } d->in_dir = 0; if (++d->curlvl2 < Config.cacheSwap.swapDirs[d->dirn].l2) Index: squid/src/store_swapin.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/store_swapin.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/store_swapin.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/store_swapin.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: store_swapin.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: store_swapin.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 20 Storage Manager Swapin Functions * AUTHOR: Duane Wessels @@ -89,6 +89,7 @@ } ctrlp->path = xstrdup(storeSwapFullPath(e->swap_file_number, NULL)); debug(20, 3) ("storeSwapInValidateComplete: Opening %s\n", ctrlp->path); + store_open_disk_fd++; file_open(ctrlp->path, O_RDONLY, storeSwapInFileOpened, @@ -106,6 +107,7 @@ if (fd == -2 && errcode == -2) { xfree(ctrlp->path); xfree(ctrlp); + store_open_disk_fd--; return; } assert(mem != NULL); @@ -116,15 +118,18 @@ "\tFile:\t'%s'\n\t URL:\t'%s'\n", ctrlp->path, storeUrl(e)); storeEntryDump(e, 3); + store_open_disk_fd--; } else if (e->swap_status != SWAPOUT_DONE) { (void) 0; } else if (fstat(fd, &sb) < 0) { debug(20, 1) ("storeSwapInFileOpened: fstat() FD %d: %s\n", fd, xstrerror()); file_close(fd); + store_open_disk_fd--; fd = -1; } else if (sb.st_size == 0 || sb.st_size != e->swap_file_sz) { debug(20, 1) ("storeSwapInFileOpened: %s: Size mismatch: %d(fstat) != %d(object)\n", ctrlp->path, (int) sb.st_size, e->swap_file_sz); file_close(fd); + store_open_disk_fd--; fd = -1; } if (fd < 0) { Index: squid/src/store_swapout.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/store_swapout.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/store_swapout.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/store_swapout.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: store_swapout.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: store_swapout.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 20 Storage Manager Swapout Functions * AUTHOR: Duane Wessels @@ -43,14 +43,16 @@ static FOCB storeSwapOutFileOpened; static off_t storeSwapOutObjectBytesOnDisk(const MemObject *); +static void storeSwapOutStart(StoreEntry * e); +static DWCB storeSwapOutHandle; /* start swapping object to disk */ -void +static void storeSwapOutStart(StoreEntry * e) { swapout_ctrl_t *ctrlp = xmalloc(sizeof(swapout_ctrl_t)); assert(e->mem_obj); - cbdataAdd(ctrlp, MEM_NONE); + cbdataAdd(ctrlp, cbdataXfree, 0); storeLockObject(e); e->swap_file_number = storeDirMapAllocate(); ctrlp->swapfilename = xstrdup(storeSwapFullPath(e->swap_file_number, NULL)); @@ -58,6 +60,7 @@ ctrlp->oldswapstatus = e->swap_status; e->swap_status = SWAPOUT_OPENING; e->mem_obj->swapout.ctrl = ctrlp; + store_open_disk_fd++; file_open(ctrlp->swapfilename, O_WRONLY | O_CREAT | O_TRUNC, storeSwapOutFileOpened, @@ -65,7 +68,7 @@ e); } -void +static void storeSwapOutHandle(int fdnotused, int flag, size_t len, void *data) { swapout_ctrl_t *ctrlp = data; @@ -133,27 +136,28 @@ char *swap_buf; ssize_t swap_buf_len; int hdr_len = 0; - assert(mem != NULL); + if (mem == NULL) + return; /* should we swap something out to disk? */ - debug(20, 3) ("storeCheckSwapOut: %s\n", storeUrl(e)); - debug(20, 3) ("storeCheckSwapOut: store_status = %s\n", + debug(20, 7) ("storeCheckSwapOut: %s\n", storeUrl(e)); + debug(20, 7) ("storeCheckSwapOut: store_status = %s\n", storeStatusStr[e->store_status]); - if (e->store_status == STORE_ABORTED) { + if (EBIT_TEST(e->flags, ENTRY_ABORTED)) { assert(EBIT_TEST(e->flags, RELEASE_REQUEST)); storeSwapOutFileClose(e); return; } - debug(20, 3) ("storeCheckSwapOut: mem->inmem_lo = %d\n", + debug(20, 7) ("storeCheckSwapOut: mem->inmem_lo = %d\n", (int) mem->inmem_lo); - debug(20, 3) ("storeCheckSwapOut: mem->inmem_hi = %d\n", + debug(20, 7) ("storeCheckSwapOut: mem->inmem_hi = %d\n", (int) mem->inmem_hi); - debug(20, 3) ("storeCheckSwapOut: swapout.queue_offset = %d\n", + debug(20, 7) ("storeCheckSwapOut: swapout.queue_offset = %d\n", (int) mem->swapout.queue_offset); - debug(20, 3) ("storeCheckSwapOut: swapout.done_offset = %d\n", + debug(20, 7) ("storeCheckSwapOut: swapout.done_offset = %d\n", (int) mem->swapout.done_offset); #if USE_ASYNC_IO if (mem->inmem_hi < mem->swapout.queue_offset) { - storeAbort(e, 0); + storeAbort(e); assert(EBIT_TEST(e->flags, RELEASE_REQUEST)); storeSwapOutFileClose(e); return; @@ -162,7 +166,7 @@ assert(mem->inmem_hi >= mem->swapout.queue_offset); #endif lowest_offset = storeLowestMemReaderOffset(e); - debug(20, 3) ("storeCheckSwapOut: lowest_offset = %d\n", + debug(20, 7) ("storeCheckSwapOut: lowest_offset = %d\n", (int) lowest_offset); new_mem_lo = lowest_offset; assert(new_mem_lo >= mem->inmem_lo); @@ -182,11 +186,11 @@ if (!storeSwapOutAble(e)) return; swapout_size = (size_t) (mem->inmem_hi - mem->swapout.queue_offset); - debug(20, 3) ("storeCheckSwapOut: swapout_size = %d\n", + debug(20, 7) ("storeCheckSwapOut: swapout_size = %d\n", (int) swapout_size); if (swapout_size == 0) { if (e->store_status == STORE_OK && !storeSwapOutWriteQueued(mem)) { - debug(20, 3) ("storeCheckSwapOut: nothing to write for STORE_OK\n"); + debug(20, 7) ("storeCheckSwapOut: nothing to write for STORE_OK\n"); if (e->swap_file_number > -1) { storeUnlinkFileno(e->swap_file_number); storeDirMapBitReset(e->swap_file_number); @@ -235,7 +239,7 @@ storeDirMapBitReset(e->swap_file_number); e->swap_file_number = -1; e->swap_status = SWAPOUT_NONE; - memFree(MEM_DISK_BUF, swap_buf); + memFree(swap_buf, MEM_DISK_BUF); storeReleaseRequest(e); storeSwapOutFileClose(e); return; @@ -269,6 +273,7 @@ } ctrlp = mem->swapout.ctrl; file_close(mem->swapout.fd); + store_open_disk_fd--; mem->swapout.fd = -1; xfree(ctrlp->swapfilename); cbdataFree(ctrlp); @@ -289,18 +294,25 @@ xfree(ctrlp->swapfilename); cbdataFree(ctrlp); mem->swapout.ctrl = NULL; + store_open_disk_fd--; return; } assert(e->swap_status == SWAPOUT_OPENING); if (fd < 0) { debug(20, 0) ("storeSwapOutFileOpened: Unable to open swapfile: %s\n\t%s\n", ctrlp->swapfilename, xstrerror()); - storeDirMapBitReset(e->swap_file_number); + /* + * yuck. don't clear the filemap bit for some errors so that + * we don't try re-using it over and over + */ + if (errno != EPERM) + storeDirMapBitReset(e->swap_file_number); e->swap_file_number = -1; e->swap_status = ctrlp->oldswapstatus; xfree(ctrlp->swapfilename); cbdataFree(ctrlp); mem->swapout.ctrl = NULL; + store_open_disk_fd--; return; } mem->swapout.fd = (short) fd; Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/structs.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/structs.h 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,9 +1,6 @@ - - - /* - * $Id: structs.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: structs.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -34,6 +31,17 @@ * */ +struct _dlink_node { + void *data; + dlink_node *prev; + dlink_node *next; +}; + +struct _dlink_list { + dlink_node *head; + dlink_node *tail; +}; + struct _acl_ip_data { struct in_addr addr1; /* if addr2 non-zero then its a range */ struct in_addr addr2; @@ -106,36 +114,6 @@ u_char *community; }; -struct _viewEntry { - char viewName[32]; - int viewIndex; - int viewType; - int viewSubtreeLen; - oid viewSubtree[32]; - struct _viewEntry *next; -}; - -struct _communityEntry { - char name[64]; - int readView; - int writeView; - acl_access *acls; - communityEntry *next; -}; - -struct _usecEntry { - u_char userName[32]; - int userLen; - int qoS; - u_char authKey[16]; - u_char privKey[16]; - int noauthReadView; - int noauthWriteView; - int authReadView; - int authWriteView; - usecEntry *next; -}; - #endif struct _acl { @@ -163,11 +141,18 @@ const acl_access *access_list; struct in_addr src_addr; struct in_addr dst_addr; + struct in_addr my_addr; request_t *request; +#if USE_IDENT + ConnStateData *conn; /* hack for ident */ char ident[USER_IDENT_SZ]; +#endif char browser[BROWSERNAMELEN]; acl_proxy_auth_user *auth_user; acl_lookup_state state[ACL_ENUM_MAX]; +#if SQUID_SNMP + char *snmp_community; +#endif PF *callback; void *callback_data; }; @@ -205,11 +190,28 @@ }; #if DELAY_POOLS -struct _delay_spec { +struct _delaySpec { int restore_bps; int max_bytes; }; +/* malloc()'d only as far as used (class * sizeof(delaySpec)! + * order of elements very important! + */ +struct _delaySpecSet { + delaySpec aggregate; + delaySpec individual; + delaySpec network; +}; + +struct _delayConfig { + unsigned short pools; + unsigned short initial; + unsigned char *class; + delaySpecSet **rates; + acl_access **access; +}; + #endif struct _SquidConfig { @@ -217,10 +219,12 @@ size_t maxSize; int highWaterMark; int lowWaterMark; - } Mem , Swap; + } Swap; + size_t memMaxSize; struct { char *relayHost; u_short relayPort; + peer *peer; } Wais; struct { size_t min; @@ -242,6 +246,9 @@ time_t deadPeer; int icp_query; /* msec */ int mcast_icp_query; /* msec */ +#if USE_IDENT + time_t ident; +#endif } Timeout; size_t maxRequestSize; struct { @@ -258,16 +265,7 @@ struct { char *configFile; char *agentInfo; - char *mibPath; - char *trap_community; - char *trap_sink; u_short localPort; - int do_queueing; - int conf_authtraps; - wordlist *snmpconf; - viewEntry *views; - usecEntry *users; - communityEntry *communities; } Snmp; #endif char *as_whois_server; @@ -364,7 +362,6 @@ #endif int common_log; int log_mime_hdrs; - int ident_lookup; int log_fqdn; int announce; int accel_with_proxy; @@ -377,6 +374,8 @@ int offline; int redir_rewrites_host; int persistent_client_posts; + int prefer_direct; + int strip_query_terms; } onoff; acl *aclList; struct { @@ -387,6 +386,13 @@ acl_access *AlwaysDirect; acl_access *ASlists; acl_access *noCache; +#if SQUID_SNMP + acl_access *snmp; +#endif + acl_access *brokenPosts; +#if USE_IDENT + acl_access *identLookup; +#endif } accessList; acl_deny_info_list *denyInfoList; char *proxyAuthRealm; @@ -414,23 +420,7 @@ size_t limit; } MemPools; #if DELAY_POOLS - struct { - struct { - struct _delay_spec aggregate; - acl_access *access; - } class1; - struct { - struct _delay_spec aggregate; - struct _delay_spec individual; - acl_access *access; - } class2; - struct { - struct _delay_spec aggregate; - struct _delay_spec individual; - struct _delay_spec network; - acl_access *access; - } class3; - } Delay; + delayConfig Delay; #endif struct { int icp_average; @@ -441,6 +431,15 @@ int max_open_disk_fds; int uri_whitespace; size_t rangeOffsetLimit; +#if MULTICAST_MISS_STREAM + struct { + struct in_addr addr; + unsigned short port; + char *encode_key; + } mcast_miss; +#endif + HttpHeaderMask anonymize_headers; + char *coredump_dir; }; struct _SquidConfig2 { @@ -505,12 +504,12 @@ struct _fde { unsigned int type; - unsigned int open; u_short local_port; u_short remote_port; char ipaddr[16]; /* dotted decimal address of peer */ char desc[FD_DESC_SZ]; struct { + unsigned int open:1; unsigned int close_request:1; unsigned int write_daemon:1; unsigned int closing:1; @@ -705,6 +704,7 @@ struct _http_state_flags { unsigned int proxying:1; unsigned int keepalive:1; + unsigned int only_if_cached:1; }; struct _HttpStateData { @@ -717,7 +717,7 @@ request_t *orig_request; int fd; http_state_flags flags; - FwdState *fwdState; + FwdState *fwd; }; struct _icpUdpData { @@ -818,6 +818,7 @@ http_status status; char *location; } redirect; + dlink_node active; }; struct _ConnStateData { @@ -831,13 +832,7 @@ struct sockaddr_in peer; struct sockaddr_in me; struct in_addr log_addr; - struct { - int fd; - char ident[USER_IDENT_SZ]; - IDCB *callback; - int state; - void *callback_data; - } ident; + char ident[USER_IDENT_SZ]; int nrequests; int persistent; struct { @@ -846,17 +841,6 @@ } defer; }; -struct _dlink_node { - void *data; - dlink_node *prev; - dlink_node *next; -}; - -struct _dlink_list { - dlink_node *head; - dlink_node *tail; -}; - struct _ipcache_addrs { struct in_addr *in_addrs; unsigned char *bad_mask; @@ -940,13 +924,19 @@ }; struct _DigestFetchState { - peer *peer; + PeerDigest *pd; StoreEntry *entry; StoreEntry *old_entry; + request_t *request; int offset; int mask_offset; time_t start_time; - request_t *request; + time_t resp_time; + time_t expires; + struct { + int msg; + int bytes; + } sent, recv; }; /* statistics for cache digests and other hit "predictors" */ @@ -960,24 +950,33 @@ }; struct _PeerDigest { - CacheDigest *cd; + peer *peer; /* pointer back to peer structure, argh */ + CacheDigest *cd; /* actual digest structure */ + String host; /* copy of peer->host */ + const char *req_result; /* text status of the last request */ struct { - unsigned int inited:1; /* initialized */ - unsigned int usable:1; /* ready to use */ + unsigned int needed:1; /* there were requests for this digest */ + unsigned int usable:1; /* can be used for lookups */ unsigned int requested:1; /* in process of receiving [fresh] digest */ - unsigned int disabled:1; /* do not use/validate the digest */ - unsigned int init_pending:1; } flags; - time_t last_fetch_resp_time; - time_t last_req_timestamp; - time_t last_dis_delay; /* last disability delay */ + struct { + /* all times are absolute unless augmented with _delay */ + time_t initialized; /* creation */ + time_t needed; /* first lookup/use by a peer */ + time_t next_check; /* next scheduled check/refresh event */ + time_t retry_delay; /* delay before re-checking _invalid_ digest */ + time_t requested; /* requested a fresh copy of a digest */ + time_t req_delay; /* last request response time */ + time_t received; /* received the current copy of a digest */ + time_t disabled; /* disabled for good */ + } times; struct { cd_guess_stats guess; int used_count; - int msgs_sent; - int msgs_recv; - kb_t kbytes_sent; - kb_t kbytes_recv; + struct { + int msgs; + kb_t kbytes; + } sent, recv; } stats; }; @@ -1012,7 +1011,7 @@ } htcp; #endif u_short http_port; - domain_ping *pinglist; + domain_ping *peer_domain; domain_type *typelist; acl_access *access; struct { @@ -1044,7 +1043,7 @@ } flags; } mcast; #if USE_CACHE_DIGESTS - PeerDigest digest; + PeerDigest *digest; #endif int tcp_up; /* 0 if a connect() fails */ time_t last_fail_time; @@ -1100,9 +1099,10 @@ StoreEntry *entry; int always_direct; int never_direct; + int direct; PSC *callback; - PSC *fail_callback; void *callback_data; + FwdServer *servers; /* * Why are these struct sockaddr_in instead of peer *? Because a * peer structure can become invalid during the peer selection @@ -1112,6 +1112,15 @@ */ struct sockaddr_in first_parent_miss; struct sockaddr_in closest_parent_miss; + /* + * ->hit and ->secho can be peer* because they should only be + * accessed during the thread when they are set + */ + peer *hit; + peer_t hit_type; +#if ALLOW_SOURCE_PING + peer *secho; +#endif ping_data ping; aclCheck_t *acl_checklist; }; @@ -1246,12 +1255,12 @@ int l2; int cur_size; int max_size; - int read_only; int suggest; fileMap *map; int swaplog_fd; struct { unsigned int selected:1; + unsigned int read_only:1; } flags; }; @@ -1289,20 +1298,17 @@ request_flags flags; HttpHdrCc *cache_control; HttpHdrRange *range; - time_t max_age; float http_ver; time_t ims; int imslen; int max_forwards; struct in_addr client_addr; + struct in_addr my_addr; HttpHeader header; char *body; size_t body_sz; HierarchyLogEntry hier; err_type err_type; -#if DELAY_POOLS - delay_id delay_id; -#endif char *peer_login; /* Configured peer login:password */ }; @@ -1537,6 +1543,7 @@ MemMeter inuse; MemMeter idle; gb_t saved; + gb_t total; }; /* a pool is a [growing] space for objects of the same size */ @@ -1576,26 +1583,24 @@ int del_count; /* number of deletions performed so far */ }; +struct _FwdServer { + peer *peer; /* NULL --> origin server */ + hier_code code; + FwdServer *next; +}; + struct _FwdState { int client_fd; StoreEntry *entry; request_t *request; FwdServer *servers; int server_fd; - struct { - int err_code; - http_status http_code; - int xerrno; - } fail; + ErrorState *err; time_t start; int n_tries; -}; - -struct _FwdServer { - char *host; - u_short port; - peer *peer; - struct _FwdServer *next; + struct { + unsigned int dont_retry:1; + } flags; }; #if USE_HTCP Index: squid/src/tools.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/tools.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/tools.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/tools.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: tools.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: tools.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 21 Misc Functions * AUTHOR: Harvest Derived @@ -108,7 +108,7 @@ fprintf(debug_log, "\tTotal free: %6d KB %d%%\n", (int) (ms.bytes_free >> 10), percent(ms.bytes_free, ms.bytes_total)); -#elif HAVE_MALLINFO +#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO struct mallinfo mp; int t; if (!do_mallinfo) @@ -175,6 +175,11 @@ (double) r->ru_utime.tv_usec / 1000000.0; } +/* Hack for some HP-UX preprocessors */ +#ifndef HAVE_GETPAGESIZE +#define HAVE_GETPAGESIZE 0 +#endif + int rusage_maxrss(struct rusage *r) { @@ -298,8 +303,7 @@ fatal_common(const char *message) { #if HAVE_SYSLOG - if (opt_syslog_enable) - syslog(LOG_ALERT, "%s", message); + syslog(LOG_ALERT, "%s", message); #endif fprintf(debug_log, "FATAL: %s\n", message); if (opt_debug_stderr && debug_log != stderr) @@ -322,11 +326,11 @@ if (!store_rebuilding) storeDirWriteCleanLogs(0); fatal_common(message); - exit(1); + exit(shutting_down ? 0 : 1); } /* printf-style interface for fatal */ -#ifdef __STDC__ +#if STDC_HEADERS void fatalf(const char *fmt,...) { @@ -807,6 +811,8 @@ static int call_id = 0; double value = gb_to_double(g); char *buf = bufs[call_id++]; + if (call_id >= max_cc_calls) + call_id = 0; /* select format */ if (value < 1e9) snprintf(buf, sizeof(GbBuf), "%.2f MB", value / 1e6); Index: squid/src/typedefs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/typedefs.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/typedefs.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/typedefs.h 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: typedefs.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: typedefs.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -163,10 +163,14 @@ typedef struct _generic_cbdata generic_cbdata; #if SQUID_SNMP +typedef variable_list *(oid_ParseFn) (variable_list *, snint *); typedef struct _snmp_request_t snmp_request_t; -typedef struct _viewEntry viewEntry; -typedef struct _communityEntry communityEntry; -typedef struct _usecEntry usecEntry; +#endif + +#if DELAY_POOLS +typedef struct _delayConfig delayConfig; +typedef struct _delaySpecSet delaySpecSet; +typedef struct _delaySpec delaySpec; #endif /* define AIOCB even without USE_ASYNC_IO */ @@ -175,16 +179,17 @@ typedef void CNCB(int fd, int status, void *); typedef void FREE(void *); +typedef void CBDUNL(void *, int); typedef void FOCB(void *, int fd, int errcode); typedef void EVH(void *); typedef void PF(int, void *); typedef void DRCB(int fd, const char *buf, int size, int errflag, void *data); typedef void DWCB(int, int, size_t, void *); typedef void FQDNH(const char *, void *); -typedef void IDCB(void *); +typedef void IDCB(const char *ident, void *data); typedef void IPH(const ipcache_addrs *, void *); typedef void IRCB(peer *, peer_t, protocol_t, void *, void *data); -typedef void PSC(peer *, void *); +typedef void PSC(FwdServer *, void *); typedef void RH(void *data, char *); typedef void UH(void *data, wordlist *); typedef int DEFER(int fd, void *data); @@ -205,7 +210,7 @@ /* append/vprintf's for Packer */ typedef void (*append_f) (void *, const char *buf, int size); -#ifdef __STDC__ +#if STDC_HEADERS typedef void (*vprintf_f) (void *, const char *fmt, va_list args); #else typedef void (*vprintf_f) (); @@ -233,7 +238,7 @@ typedef void (*ObjPackMethod) (void *obj, Packer * p); #if DELAY_POOLS -typedef int delay_id; +typedef unsigned int delay_id; #endif #if USE_HTCP Index: squid/src/unlinkd.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/unlinkd.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/unlinkd.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/unlinkd.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: unlinkd.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: unlinkd.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 12 Unlink Daemon * AUTHOR: Duane Wessels @@ -32,30 +32,12 @@ * */ +#include "squid.h" + #ifdef UNLINK_DAEMON /* This is the external unlinkd process */ -#include "config.h" - -#if HAVE_LIBC_H -#include -#endif -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_STDLIB_H -#include -#endif -#if HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_STRINGS_H -#include -#endif #define UNLINK_BUF_LEN 1024 int @@ -63,11 +45,21 @@ { char buf[UNLINK_BUF_LEN]; char *t; + int x; setbuf(stdin, NULL); + setbuf(stdout, NULL); while (fgets(buf, UNLINK_BUF_LEN, stdin)) { if ((t = strchr(buf, '\n'))) *t = '\0'; - unlink(buf); +#if USE_TRUNCATE_NOT_UNLINK + x = truncate(buf, 0); +#else + x = unlink(buf); +#endif + if (x < 0) + printf("ERR\n"); + else + printf("OK\n"); } exit(0); } @@ -76,36 +68,79 @@ /* This code gets linked to Squid */ -#include "squid.h" - #if USE_UNLINKD static int unlinkd_wfd = -1; static int unlinkd_rfd = -1; #endif +#define UNLINKD_QUEUE_LIMIT 20 + void unlinkdUnlink(const char *path) { #if USE_UNLINKD - char *buf; + 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; } - l = strlen(path) + 1; - buf = xcalloc(1, l + 1); - strcpy(buf, path); - strcat(buf, "\n"); - file_write(unlinkd_wfd, - -1, - buf, - l, - NULL, /* Handler */ - NULL, /* Handler-data */ - xfree); + /* + * 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; + int x; + FD_ZERO(&R); + FD_SET(unlinkd_rfd, &R); + to.tv_sec = 0; + to.tv_usec = 100000; + x = 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(50, 1) ("unlinkdUnlink: write FD %d failed: %s\n", + unlinkd_wfd, xstrerror()); + safeunlink(path, 0); + return; + } else if (x != l) { + debug(50, 1) ("unlinkdUnlink: FD %d only wrote %d of %d bytes\n", + unlinkd_wfd, x, l); + safeunlink(path, 0); + return; + } Counter.unlink.requests++; + queuelen++; #endif } @@ -152,7 +187,11 @@ fd_note(unlinkd_rfd, "unlinkd -> squid"); commSetTimeout(unlinkd_rfd, -1, NULL, NULL); commSetTimeout(unlinkd_wfd, -1, NULL, NULL); - commSetNonBlocking(unlinkd_wfd); + /* + * We leave unlinkd_wfd blocking, because we never want to lose an + * unlink request, and we don't have code to retry if we get + * EWOULDBLOCK. + */ commSetNonBlocking(unlinkd_rfd); debug(12, 1) ("Unlinkd pipe opened on FD %d\n", unlinkd_wfd); #endif Index: squid/src/url.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/url.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/url.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/url.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: url.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: url.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 23 URL Parsing * AUTHOR: Duane Wessels @@ -233,7 +233,7 @@ } } for (t = host; *t; t++) - *t = tolower(*t); + *t = xtolower(*t); if (strspn(host, valid_hostname_chars) != strlen(host)) { debug(23, 1) ("urlParse: Illegal character in hostname '%s'\n", host); return NULL; @@ -256,7 +256,7 @@ } #endif if (stringHasWhitespace(urlpath)) { - debug(23, 1) ("urlParse: URI has whitespace: {%s}\n", url); + debug(23, 2) ("urlParse: URI has whitespace: {%s}\n", url); switch (Config.uri_whitespace) { case URI_WHITESPACE_DENY: return NULL; @@ -350,8 +350,9 @@ /* * strip arguments AFTER a question-mark */ - if ((t = strchr(buf, '?'))) - *(++t) = '\0'; + if (Config.onoff.strip_query_terms) + if ((t = strchr(buf, '?'))) + *(++t) = '\0'; break; } } Index: squid/src/urn.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/urn.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/urn.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/urn.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,7 +1,7 @@ /* * - * $Id: urn.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: urn.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 52 URN Parsing * AUTHOR: Kostas Anagnostakis @@ -109,7 +109,7 @@ urnState = xcalloc(1, sizeof(UrnState)); urnState->entry = e; urnState->request = requestLink(r); - cbdataAdd(urnState, MEM_NONE); + cbdataAdd(urnState, cbdataXfree, 0); storeLockObject(urnState->entry); if (strncasecmp(strBuf(r->urlpath), "menu.", 5) == 0) { char *new_path = xstrdup(strBuf(r->urlpath) + 5); @@ -138,15 +138,11 @@ if ((urlres_e = storeGetPublic(urlres, METHOD_GET)) == NULL) { urlres_e = storeCreateEntry(urlres, urlres, null_request_flags, METHOD_GET); storeClientListAdd(urlres_e, urnState); - fwdStart(-1, urlres_e, urlres_r, no_addr); + fwdStart(-1, urlres_e, urlres_r, no_addr, no_addr); } else { storeLockObject(urlres_e); storeClientListAdd(urlres_e, urnState); } -#if DELAY_POOLS - urlres_r->delay_id = r->delay_id; - delaySetStoreClient(urlres_e, urnState, r->delay_id); -#endif urnState->urlres_e = urlres_e; urnState->urlres_r = requestLink(urlres_r); storeClientCopy(urlres_e, @@ -191,15 +187,15 @@ int urlcnt = 0; debug(52, 3) ("urnHandleReply: Called with size=%d.\n", size); - if (urlres_e->store_status == STORE_ABORTED) { - memFree(MEM_4K_BUF, buf); + if (EBIT_TEST(urlres_e->flags, ENTRY_ABORTED)) { + memFree(buf, MEM_4K_BUF); return; } if (size == 0) { - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); return; } else if (size < 0) { - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); return; } if (urlres_e->store_status == STORE_PENDING && size < SM_PAGE_SIZE) { @@ -232,7 +228,7 @@ errorAppendEntry(e, err); return; } - while (isspace(*s)) + while (xisspace(*s)) s++; urls = urnParseReply(s, urnState->request->method); for (i = 0; NULL != urls[i].url; i++) @@ -286,7 +282,7 @@ httpBodySet(&rep->body, &mb); httpReplySwapOut(rep, e); storeComplete(e); - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); for (i = 0; i < urlcnt; i++) { safe_free(urls[i].url); safe_free(urls[i].host); Index: squid/src/useragent.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/useragent.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/useragent.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/useragent.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: useragent.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: useragent.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 40 User-Agent logging * AUTHOR: Joe Ramey @@ -89,6 +89,11 @@ snprintf(to, MAXPATHLEN, "%s.%d", fname, i); rename(from, to); } + if (cache_useragent_log) { + file_close(fileno(cache_useragent_log)); + fclose(cache_useragent_log); + cache_useragent_log = NULL; + } /* Rotate the current log to .0 */ if (Config.Log.rotateNumber > 0) { snprintf(to, MAXPATHLEN, "%s.%d", fname, 0); Index: squid/src/wais.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/wais.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/wais.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/wais.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: wais.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: wais.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 24 WAIS Relay * AUTHOR: Harvest Derived @@ -42,6 +42,7 @@ const HttpHeader *request_hdr; char url[MAX_URL]; request_t *request; + FwdState *fwd; } WaisStateData; static PF waisStateFree; @@ -66,12 +67,14 @@ waisTimeout(int fd, void *data) { WaisStateData *waisState = data; - ErrorState *err; StoreEntry *entry = waisState->entry; debug(24, 4) ("waisTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); - err = errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT); - err->request = requestLink(waisState->request); - errorAppendEntry(entry, err); + if (entry->store_status == STORE_PENDING) { + if (entry->mem_obj->inmem_hi == 0) { + fwdFail(waisState->fwd, + errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT)); + } + } comm_close(fd); } @@ -90,6 +93,10 @@ #if DELAY_POOLS delay_id delay_id = delayMostBytesAllowed(entry->mem_obj); #endif + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { + comm_close(fd); + return; + } errno = 0; read_sz = 4096; #if DELAY_POOLS @@ -141,7 +148,7 @@ } else if (len == 0) { /* Connection closed; retrieval done. */ entry->expires = squid_curtime; - storeComplete(entry); + fwdComplete(waisState->fwd); comm_close(fd); } else { storeAppend(entry, buf, len); @@ -206,25 +213,30 @@ comm_write_mbuf(fd, mb, waisSendComplete, waisState); if (EBIT_TEST(waisState->entry->flags, ENTRY_CACHABLE)) storeSetPublicKey(waisState->entry); /* Make it public */ + EBIT_CLR(waisState->entry->flags, ENTRY_FWD_HDR_WAIT); } void -waisStart(request_t * request, StoreEntry * entry, int fd) +waisStart(FwdState * fwd) { WaisStateData *waisState = NULL; + request_t *request = fwd->request; + StoreEntry *entry = fwd->entry; + int fd = fwd->server_fd; const char *url = storeUrl(entry); method_t method = request->method; debug(24, 3) ("waisStart: \"%s %s\"\n", RequestMethodStr[method], url); Counter.server.all.requests++; Counter.server.other.requests++; waisState = xcalloc(1, sizeof(WaisStateData)); - cbdataAdd(waisState, MEM_NONE); + cbdataAdd(waisState, cbdataXfree, 0); waisState->method = method; waisState->request_hdr = &request->header; waisState->fd = fd; waisState->entry = entry; xstrncpy(waisState->url, url, MAX_URL); waisState->request = requestLink(request); + waisState->fwd = fwd; comm_add_close_handler(waisState->fd, waisStateFree, waisState); storeLockObject(entry); commSetSelect(fd, COMM_SELECT_WRITE, waisSendRequest, waisState, 0); Index: squid/src/whois.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/whois.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/whois.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/whois.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,6 @@ + /* - * $Id: whois.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: whois.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 75 WHOIS protocol * AUTHOR: Duane Wessels, Kostas Anagnostakis @@ -39,7 +40,7 @@ typedef struct { StoreEntry *entry; request_t *request; - FwdState *fwdState; + FwdState *fwd; } WhoisState; static PF whoisClose; @@ -49,15 +50,16 @@ /* PUBLIC */ void -whoisStart(FwdState * fwdState, int fd) +whoisStart(FwdState * fwd) { WhoisState *p = xcalloc(1, sizeof(*p)); + int fd = fwd->server_fd; char *buf; size_t l; - p->request = fwdState->request; - p->entry = fwdState->entry; - p->fwdState = fwdState; - cbdataAdd(p, MEM_NONE); + p->request = fwd->request; + p->entry = fwd->entry; + p->fwd = fwd; + cbdataAdd(p, cbdataXfree, 0); storeLockObject(p->entry); comm_add_close_handler(fd, whoisClose, p); l = strLen(p->request->urlpath) + 3; @@ -102,18 +104,20 @@ if (ignoreErrno(errno)) { commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read); } else if (entry->mem_obj->inmem_hi == 0) { - fwdFail(p->fwdState, ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, errno); + ErrorState *err; + err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR); + err->xerrno = errno; + fwdFail(p->fwd, err); comm_close(fd); } else { - storeAbort(entry, 0); comm_close(fd); } } else { - storeComplete(entry); + fwdComplete(p->fwd); debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry)); comm_close(fd); } - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); } static void Index: squid/test-suite/tcp-banger2.c =================================================================== RCS file: /cvsroot/squid-sf//squid/test-suite/tcp-banger2.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/test-suite/tcp-banger2.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/test-suite/tcp-banger2.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,7 @@ #include "config.h" +/* $Id: tcp-banger2.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ */ + /* * On some systems, FD_SETSIZE is set to something lower than the * actual number of files which can be opened. IRIX is one case, @@ -82,6 +84,9 @@ #if HAVE_ASSERT_H #include #endif +#if HAVE_CTYPE_H +#include +#endif #define PROXY_PORT 3128 #define PROXY_ADDR "127.0.0.1" @@ -94,6 +99,7 @@ static int nrequests; static int opt_ims = 0; static int opt_range = 0; +static int opt_accel = 0; static int max_connections = 64; static time_t lifetime = 60; static time_t process_lifetime = 86400; @@ -121,6 +127,7 @@ int validsize; int bodysize; int content_length; + int status; long validsum; long sum; }; @@ -133,9 +140,9 @@ static void free_request(struct _request *r) { - if (r->url) - free(r->url); - free(r); + if (r->url) + free(r->url); + free(r); } char * @@ -216,9 +223,11 @@ if (!header) break; /* Decode header */ - if (strncasecmp(header, "Content-Length:", 15) == 0) + if (strncmp(header, "HTTP", 4) == 0) + r->status = atoi(header + 8); + else if (strncasecmp(header, "Content-Length:", 15) == 0) r->content_length = atoi(header + 15); - if (strncasecmp(header, "X-Request-URI:", 14) == 0) { + else if (strncasecmp(header, "X-Request-URI:", 14) == 0) { /* Check URI */ if (strncmp(r->url, header + 15, strcspn(header + 15, "\r\n"))) { char url[8192]; @@ -270,8 +279,12 @@ r->url, r->validsum, r->sum); } if (trace_file) { - fprintf(trace_file, "%s %s %s %d 0x%lx\n", - r->method, r->url, r->requestbodyfile, r->bodysize, r->sum); + if (opt_checksum) + fprintf(trace_file, "%s %s %d %s %d 0x%lx\n", + r->method, r->url, r->status, r->requestbodyfile, r->bodysize, r->sum); + else + fprintf(trace_file, "%s %s %d %s %d\n", + r->method, r->url, r->status, r->requestbodyfile, r->bodysize); } free_request(r); } @@ -283,6 +296,7 @@ char buf[4096]; char msg[8192]; char *method, *url, *file, *size, *checksum; + char *host; char urlbuf[8192]; int len, len2; time_t w; @@ -334,9 +348,19 @@ if (checksum && strcmp(checksum, "-") != 0) r->validsum = strtoul(checksum, NULL, 0); r->content_length = -1; /* Unknown */ - msg[0] = '\0'; - sprintf(buf, "%s %s HTTP/1.0\r\n", method, url); - strcat(msg, buf); + if (opt_accel) { + host = strchr(url, '/') + 2; + url = strchr(host, '/'); + } else { + host = NULL; + } + sprintf(msg, "%s %s HTTP/1.0\r\n", method, url); + if (host) { + url[0] = '\0'; + sprintf(buf, "Host: %s\r\n", host); + strcat(msg, buf); + url[0] = '/'; + } strcat(msg, "Accept: */*\r\n"); if (opt_ims && (lrand48() & 0x03) == 0) { w = time(NULL) - (lrand48() & 0x3FFFF); @@ -441,6 +465,7 @@ fprintf(stderr, " -c Check checksum agains trace\n"); fprintf(stderr, " -i Send random If-Modified-Since times\n"); fprintf(stderr, " -l Connection lifetime timeout (default 60)\n"); + fprintf(stderr, " -a Accelerator mode\n"); } int @@ -461,8 +486,11 @@ progname = strdup(argv[0]); gettimeofday(&now, NULL); start = last = now; - while ((c = getopt(argc, argv, "p:h:n:icrl:L:t:")) != -1) { + while ((c = getopt(argc, argv, "ap:h:n:icrl:L:t:")) != -1) { switch (c) { + case 'a': + opt_accel = 1; + break; case 'p': proxy_port = atoi(optarg); break; @@ -485,9 +513,9 @@ opt_checksum = 1; break; case 't': - opt_checksum = 1; /* Tracing requires checksums */ - trace_file = fopen(optarg, "w"); + trace_file = fopen(optarg, "a"); assert(trace_file); + setbuf(trace_file, NULL); break; case 'r': opt_range = 1; @@ -550,9 +578,12 @@ (int) total_bytes_read / 1024 / 1024, (int) total_bytes_read / 1024 / dt); reqpersec = 0; - if (dt > process_lifetime) - exit(0); + /* + * if (dt > process_lifetime) + * exit(0); + */ } } + printf("Exiting normally\n"); return 0; } Index: squid/test-suite/tcp-banger3.c =================================================================== RCS file: /cvsroot/squid-sf//squid/test-suite/tcp-banger3.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/test-suite/tcp-banger3.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/test-suite/tcp-banger3.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -136,8 +136,10 @@ *t = '\0'; port = (unsigned short) atoi(t + 1); } +#if 0 if ((int) port != 80) return 0; +#endif t = strchr(url + 7, '/'); strncpy(path, (t ? t : "/"), URL_BUF_SZ); memset(&S, '\0', sizeof(S));