---------------------
PatchSet 8103 
Date: 2006/05/31 10:19:59
Author: serassio
Branch: nt
Tag: (none) 
Log:
Manually merge with HEAD after a Sourgeforce problem durin latest
cvsmerge, grrrrrr ......

Members: 
	CONTRIBUTORS:1.24.2.1->1.24.2.2 
	ChangeLog:1.44.2.11->1.44.2.12 
	doc/Makefile.am:1.5.8.1->1.5.8.2 
	doc/cachemgr.cgi.8.in:1.2->1.2.10.1 
	doc/squid.8.in:1.2.10.2->1.2.10.3 
	src/cf.data.pre:1.100.2.11->1.100.2.12 
	src/client_side.c:1.89.2.14->1.89.2.15 
	src/htcp.c:1.16->1.16.6.1 
	src/protos.h:1.74.2.14->1.74.2.15 
	src/structs.h:1.81.2.11->1.81.2.12 

Index: squid/CONTRIBUTORS
===================================================================
RCS file: /cvsroot/squid-sf//squid/CONTRIBUTORS,v
retrieving revision 1.24.2.1
retrieving revision 1.24.2.2
diff -u -r1.24.2.1 -r1.24.2.2
--- squid/CONTRIBUTORS	18 May 2006 18:34:19 -0000	1.24.2.1
+++ squid/CONTRIBUTORS	31 May 2006 10:19:59 -0000	1.24.2.2
@@ -93,5 +93,8 @@
 	Flavio Pescuma <flavio@marasystems.com>
 	Paul Armstrong <squid@otoh.org>
 	Steven Wilton <swilton@q-net.net.au>
+	Felix Meschberger <felix.meschberger@day.com>
+	Mark Bergsma <mark@nedworks.org>
+	Tim Starling <tstarling@wikimedia.org>
 
 	Duane Wessels <wessels@squid-cache.org>
Index: squid/ChangeLog
===================================================================
RCS file: /cvsroot/squid-sf//squid/ChangeLog,v
retrieving revision 1.44.2.11
retrieving revision 1.44.2.12
diff -u -r1.44.2.11 -r1.44.2.12
--- squid/ChangeLog	30 May 2006 10:28:51 -0000	1.44.2.11
+++ squid/ChangeLog	31 May 2006 10:19:59 -0000	1.44.2.12
@@ -42,6 +42,8 @@
 	  request details (browser, language etc).
 	- umask now defaults to 027 to protect the content of cache and
 	  log files from local users
+	- HTCP support for access control and the CRL operation for
+	  purgeing of cache content
 
 Changes to squid-2.5.STABLE14 (20 May 2006)
 	- [Minor] icons not displayed when visible_hostname is a
Index: squid/doc/Makefile.am
===================================================================
RCS file: /cvsroot/squid-sf//squid/doc/Makefile.am,v
retrieving revision 1.5.8.1
retrieving revision 1.5.8.2
diff -u -r1.5.8.1 -r1.5.8.2
--- squid/doc/Makefile.am	16 May 2006 21:05:57 -0000	1.5.8.1
+++ squid/doc/Makefile.am	31 May 2006 10:20:00 -0000	1.5.8.2
@@ -16,6 +16,7 @@
 	s%@DEFAULT_CACHEMGR_CONFIG@%$(DEFAULT_CACHEMGR_CONFIG)%g;\
 	s%@DEFAULT_ERROR_DIR@%$(DEFAULT_ERROR_DIR)%g;\
 	s%@DEFAULT_MIME_TABLE@%$(DEFAULT_MIME_TABLE)%g;\
+	s%@""PACKAGE_STRING""@%$(PACKAGE_STRING)%g;\
 	"
 
 squid.8: $(srcdir)/squid.8.in Makefile
Index: squid/doc/cachemgr.cgi.8.in
===================================================================
RCS file: /cvsroot/squid-sf//squid/doc/cachemgr.cgi.8.in,v
retrieving revision 1.2
retrieving revision 1.2.10.1
diff -u -r1.2 -r1.2.10.1
--- squid/doc/cachemgr.cgi.8.in	28 Apr 2006 11:10:45 -0000	1.2
+++ squid/doc/cachemgr.cgi.8.in	31 May 2006 10:20:00 -0000	1.2.10.1
@@ -1,4 +1,4 @@
-.TH cachemgr.cgi 8 2005-04-25 "squid 2.5.STABLE10"
+.TH cachemgr.cgi 8 2005-04-25 "@PACKAGE_STRING@"
 .\" Copyright and licensing information
 .\" goes here.
 .SH NAME
Index: squid/doc/squid.8.in
===================================================================
RCS file: /cvsroot/squid-sf//squid/doc/squid.8.in,v
retrieving revision 1.2.10.2
retrieving revision 1.2.10.3
diff -u -r1.2.10.2 -r1.2.10.3
--- squid/doc/squid.8.in	30 May 2006 21:03:31 -0000	1.2.10.2
+++ squid/doc/squid.8.in	31 May 2006 10:20:00 -0000	1.2.10.3
@@ -1,4 +1,4 @@
-.TH squid 8 2006-05-29 "squid 2.6.PRE1"
+.TH squid 8 2006-05-29 "@PACKAGE_STRING@"
 .\" Copyright and licensing information
 .\" goes here.
 .SH NAME
Index: squid/src/cf.data.pre
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/cf.data.pre,v
retrieving revision 1.100.2.11
retrieving revision 1.100.2.12
diff -u -r1.100.2.11 -r1.100.2.12
--- squid/src/cf.data.pre	30 May 2006 19:05:59 -0000	1.100.2.11
+++ squid/src/cf.data.pre	31 May 2006 10:20:00 -0000	1.100.2.12
@@ -1,6 +1,6 @@
 
 #
-# $Id: cf.data.pre,v 1.100.2.11 2006/05/30 19:05:59 serassio Exp $
+# $Id: cf.data.pre,v 1.100.2.12 2006/05/31 10:20:00 serassio Exp $
 #
 #
 # SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -2846,6 +2846,44 @@
 DOC_END
 
 
+NAME: htcp_access
+IFDEF: USE_HTCP
+TYPE: acl_access
+LOC: Config.accessList.htcp
+DEFAULT: none
+DEFAULT_IF_NONE: deny all
+DOC_START
+	Allowing or Denying access to the HTCP port based on defined
+	access lists
+
+	htcp_access  allow|deny [!]aclname ...
+
+	See http_access for details
+
+#Allow HTCP queries from everyone
+htcp_access allow all
+DOC_END
+
+NAME: htcp_clr_access
+IFDEF: USE_HTCP
+TYPE: acl_access
+LOC: Config.accessList.htcp_clr
+DEFAULT: none
+DEFAULT_IF_NONE: deny all
+DOC_START
+	Allowing or Denying access to purge content using HTCP based
+	on defined access lists
+
+	htcp_clr_access  allow|deny [!]aclname ...
+
+	See http_access for details
+
+#Allow HTCP CLR requests from trusted peers
+acl htcp_clr_peer src 172.16.1.2
+htcp_clr_access allow htcp_clr_peer
+DOC_END
+
+
 NAME: miss_access
 TYPE: acl_access
 LOC: Config.accessList.miss
Index: squid/src/client_side.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v
retrieving revision 1.89.2.14
retrieving revision 1.89.2.15
diff -u -r1.89.2.14 -r1.89.2.15
--- squid/src/client_side.c	30 May 2006 20:10:06 -0000	1.89.2.14
+++ squid/src/client_side.c	31 May 2006 10:20:01 -0000	1.89.2.15
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.c,v 1.89.2.14 2006/05/30 20:10:06 serassio Exp $
+ * $Id: client_side.c,v 1.89.2.15 2006/05/31 10:20:01 serassio Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -148,14 +148,18 @@
 static int clientRequestBodyTooLarge(squid_off_t clen);
 static void clientProcessBody(ConnStateData * conn);
 static void clientEatRequestBody(clientHttpRequest *);
-static void clientAccessCheckDone2(int answer, void *data);
+static void clientAccessCheck(void *data);
+static void clientAccessCheckDone(int answer, void *data);
 static void clientAccessCheck2(void *data);
+static void clientAccessCheckDone2(int answer, void *data);
 static BODY_HANDLER clientReadBody;
 static void clientAbortBody(request_t * req);
 #if USE_SSL
 static void httpsAcceptSSL(ConnStateData * connState, SSL_CTX * sslContext);
 #endif
 static int varyEvaluateMatch(StoreEntry * entry, request_t * request);
+static int modifiedSince(StoreEntry *, request_t *);
+static StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, request_flags);
 
 #if USE_IDENT
 static void
@@ -187,7 +191,7 @@
     return ch;
 }
 
-void
+static void
 clientAccessCheck(void *data)
 {
     clientHttpRequest *http = data;
@@ -220,7 +224,7 @@
 	EBIT_TEST(r->cache_control->mask, CC_ONLY_IF_CACHED);
 }
 
-StoreEntry *
+static StoreEntry *
 clientCreateStoreEntry(clientHttpRequest * h, method_t m, request_flags flags)
 {
     StoreEntry *e;
@@ -241,7 +245,7 @@
     return e;
 }
 
-void
+static void
 clientAccessCheckDone(int answer, void *data)
 {
     clientHttpRequest *http = data;
@@ -867,7 +871,7 @@
     }
 }
 
-int
+static int
 modifiedSince(StoreEntry * entry, request_t * request)
 {
     squid_off_t object_length;
@@ -901,7 +905,7 @@
     }
 }
 
-void
+static void
 clientPurgeRequest(clientHttpRequest * http)
 {
     StoreEntry *entry;
Index: squid/src/htcp.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/htcp.c,v
retrieving revision 1.16
retrieving revision 1.16.6.1
diff -u -r1.16 -r1.16.6.1
--- squid/src/htcp.c	12 May 2006 22:51:56 -0000	1.16
+++ squid/src/htcp.c	31 May 2006 10:20:01 -0000	1.16.6.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: htcp.c,v 1.16 2006/05/12 22:51:56 squidadm Exp $
+ * $Id: htcp.c,v 1.16.6.1 2006/05/31 10:20:01 serassio Exp $
  *
  * DEBUG: section 31    Hypertext Caching Protocol
  * AUTHOR: Duane Wesssels
@@ -93,6 +93,7 @@
     char *uri;
     char *version;
     char *req_hdrs;
+    request_t *request;
 };
 
 struct _htcpDetail {
@@ -155,14 +156,13 @@
 static int htcpOutSocket = -1;
 #define N_QUERIED_KEYS 256
 static cache_key queried_keys[N_QUERIED_KEYS][MD5_DIGEST_CHARS];
+static struct sockaddr_in queried_addr[N_QUERIED_KEYS];
 static MemPool *htcpSpecifierPool = NULL;
 static MemPool *htcpDetailPool = NULL;
 
-
-static char *htcpBuildPacket(htcpStuff * stuff, ssize_t * len);
+static ssize_t htcpBuildPacket(char *buf, size_t buflen, htcpStuff * stuff);
 static htcpSpecifier *htcpUnpackSpecifier(char *buf, int sz);
 static htcpDetail *htcpUnpackDetail(char *buf, int sz);
-static int htcpUnpackCountstr(char *buf, int sz, char **str);
 static ssize_t htcpBuildAuth(char *buf, size_t buflen);
 static ssize_t htcpBuildCountstr(char *buf, size_t buflen, const char *s);
 static ssize_t htcpBuildData(char *buf, size_t buflen, htcpStuff * stuff);
@@ -322,6 +322,9 @@
     case HTCP_TST:
 	off = htcpBuildTstOpData(buf + off, buflen, stuff);
 	break;
+    case HTCP_CLR:
+	// nothing to be done
+	break;
     default:
 	assert(0);
 	break;
@@ -358,40 +361,38 @@
     return off;
 }
 
-static char *
-htcpBuildPacket(htcpStuff * stuff, ssize_t * len)
+/*
+ * Build an HTCP packet into buf, maximum length buflen.
+ * Returns the packet length, or zero on failure.
+ */
+static ssize_t
+htcpBuildPacket(char *buf, size_t buflen, htcpStuff * stuff)
 {
-    size_t buflen = 8192;
     ssize_t s;
     ssize_t off = 0;
     size_t hdr_sz = sizeof(htcpHeader);
     htcpHeader hdr;
-    char *buf = xcalloc(buflen, 1);
     /* skip the header -- we don't know the overall length */
     if (buflen < hdr_sz) {
-	xfree(buf);
-	return NULL;
+	return 0;
     }
     off += hdr_sz;
     s = htcpBuildData(buf + off, buflen - off, stuff);
     if (s < 0) {
-	xfree(buf);
-	return NULL;
+	return 0;
     }
     off += s;
     s = htcpBuildAuth(buf + off, buflen - off);
     if (s < 0) {
-	xfree(buf);
-	return NULL;
+	return 0;
     }
     off += s;
     hdr.length = htons((u_short) off);
     hdr.major = 0;
     hdr.minor = 0;
     xmemcpy(buf, &hdr, hdr_sz);
-    *len = off;
     debug(31, 3) ("htcpBuildPacket: size %d\n", (int) off);
-    return buf;
+    return off;
 }
 
 static void
@@ -417,130 +418,185 @@
 static void
 htcpFreeSpecifier(htcpSpecifier * s)
 {
-    safe_free(s->method);
-    safe_free(s->uri);
-    safe_free(s->version);
-    safe_free(s->req_hdrs);
+    if (s->request)
+	requestDestroy(s->request);
     memPoolFree(htcpSpecifierPool, s);
 }
 
 static void
 htcpFreeDetail(htcpDetail * d)
 {
-    safe_free(d->resp_hdrs);
-    safe_free(d->entity_hdrs);
-    safe_free(d->cache_hdrs);
     memPoolFree(htcpDetailPool, d);
 }
 
-static int
-htcpUnpackCountstr(char *buf, int sz, char **str)
-{
-    u_short l;
-    debug(31, 3) ("htcpUnpackCountstr: sz = %d\n", sz);
-    if (sz < 2) {
-	debug(31, 3) ("htcpUnpackCountstr: sz < 2\n");
-	return -1;
-    }
-    htcpHexdump("htcpUnpackCountstr", buf, sz);
-    xmemcpy(&l, buf, 2);
-    l = ntohs(l);
-    buf += 2;
-    sz -= 2;
-    debug(31, 3) ("htcpUnpackCountstr: LENGTH = %d\n", (int) l);
-    if (sz < l) {
-	debug(31, 3) ("htcpUnpackCountstr: sz(%d) < l(%d)\n", sz, l);
-	return -1;
-    }
-    if (str) {
-	*str = xmalloc(l + 1);
-	xstrncpy(*str, buf, l + 1);
-	debug(31, 3) ("htcpUnpackCountstr: TEXT = {%s}\n", *str);
-    }
-    return (int) l + 2;
-}
-
+/*
+ * Unpack an HTCP SPECIFIER in place
+ * This will overwrite any following AUTH block
+ */
 static htcpSpecifier *
 htcpUnpackSpecifier(char *buf, int sz)
 {
     htcpSpecifier *s = memPoolAlloc(htcpSpecifierPool);
-    int o;
-    debug(31, 3) ("htcpUnpackSpecifier: %d bytes\n", (int) sz);
-    o = htcpUnpackCountstr(buf, sz, &s->method);
-    if (o < 0) {
+    method_t method;
+
+    /* Find length of METHOD */
+    u_short l = ntohs(*(u_short *) buf);
+    sz -= 2;
+    buf += 2;
+    if (l > sz) {
 	debug(31, 1) ("htcpUnpackSpecifier: failed to unpack METHOD\n");
 	htcpFreeSpecifier(s);
 	return NULL;
     }
-    buf += o;
-    sz -= o;
-    o = htcpUnpackCountstr(buf, sz, &s->uri);
-    if (o < 0) {
+    /* Set METHOD */
+    s->method = buf;
+    buf += l;
+    sz -= l;
+
+    /* Find length of URI */
+    l = ntohs(*(u_short *) buf);
+    sz -= 2;
+    if (l > sz) {
 	debug(31, 1) ("htcpUnpackSpecifier: failed to unpack URI\n");
 	htcpFreeSpecifier(s);
 	return NULL;
     }
-    buf += o;
-    sz -= o;
-    o = htcpUnpackCountstr(buf, sz, &s->version);
-    if (o < 0) {
+    /* Add terminating null to METHOD */
+    *buf = '\0';
+    /* Set URI */
+    buf += 2;
+    s->uri = buf;
+    buf += l;
+    sz -= l;
+
+    /* Find length of VERSION */
+    l = ntohs(*(u_short *) buf);
+    sz -= 2;
+    if (l > sz) {
 	debug(31, 1) ("htcpUnpackSpecifier: failed to unpack VERSION\n");
 	htcpFreeSpecifier(s);
 	return NULL;
     }
-    buf += o;
-    sz -= o;
-    o = htcpUnpackCountstr(buf, sz, &s->req_hdrs);
-    if (o < 0) {
+    /* Add terminating null to URI */
+    *buf = '\0';
+    /* Set VERSION */
+    buf += 2;
+    s->version = buf;
+    buf += l;
+    sz -= l;
+
+    /* Find length of REQ-HDRS */
+    l = ntohs(*(u_short *) buf);
+    sz -= 2;
+    if (l > sz) {
 	debug(31, 1) ("htcpUnpackSpecifier: failed to unpack REQ-HDRS\n");
 	htcpFreeSpecifier(s);
 	return NULL;
     }
-    buf += o;
-    sz -= o;
+    /* Add terminating null to URI */
+    *buf = '\0';
+    /* Set REQ-HDRS */
+    buf += 2;
+    s->req_hdrs = buf;
+    buf += l;
+    sz -= l;
+
     debug(31, 3) ("htcpUnpackSpecifier: %d bytes left\n", sz);
+    /* 
+     * Add terminating null to REQ-HDRS. This is possible because we allocated 
+     * an extra byte when we received the packet. This will overwrite any following
+     * AUTH block.
+     */
+    *buf = '\0';
+    /*
+     * Parse the request
+     */
+    method = urlParseMethod(s->method);
+    s->request = urlParse(method == METHOD_NONE ? METHOD_GET : method, s->uri);
     return s;
 }
 
+/*
+ * Unpack an HTCP DETAIL in place
+ * This will overwrite any following AUTH block
+ */
 static htcpDetail *
 htcpUnpackDetail(char *buf, int sz)
 {
     htcpDetail *d = memPoolAlloc(htcpDetailPool);
-    int o;
-    debug(31, 3) ("htcpUnpackDetail: %d bytes\n", (int) sz);
-    o = htcpUnpackCountstr(buf, sz, &d->resp_hdrs);
-    if (o < 0) {
-	debug(31, 1) ("htcpUnpackDetail: failed to unpack RESP_HDRS\n");
+
+    /* Find length of RESP-HDRS */
+    u_short l = ntohs(*(u_short *) buf);
+    sz -= 2;
+    buf += 2;
+    if (l > sz) {
+	debug(31, 1) ("htcpUnpackDetail: failed to unpack RESP-HDRS\n");
 	htcpFreeDetail(d);
 	return NULL;
     }
-    buf += o;
-    sz -= o;
-    o = htcpUnpackCountstr(buf, sz, &d->entity_hdrs);
-    if (o < 0) {
-	debug(31, 1) ("htcpUnpackDetail: failed to unpack ENTITY_HDRS\n");
+    /* Set RESP-HDRS */
+    d->resp_hdrs = buf;
+    buf += l;
+    sz -= l;
+
+    /* Find length of ENTITY-HDRS */
+    l = ntohs(*(u_short *) buf);
+    sz -= 2;
+    if (l > sz) {
+	debug(31, 1) ("htcpUnpackDetail: failed to unpack ENTITY-HDRS\n");
 	htcpFreeDetail(d);
 	return NULL;
     }
-    buf += o;
-    sz -= o;
-    o = htcpUnpackCountstr(buf, sz, &d->cache_hdrs);
-    if (o < 0) {
-	debug(31, 1) ("htcpUnpackDetail: failed to unpack CACHE_HDRS\n");
+    /* Add terminating null to RESP-HDRS */
+    *buf = '\0';
+    /* Set ENTITY-HDRS */
+    buf += 2;
+    d->entity_hdrs = buf;
+    buf += l;
+    sz -= l;
+
+    /* Find length of CACHE-HDRS */
+    l = ntohs(*(u_short *) buf);
+    sz -= 2;
+    if (l > sz) {
+	debug(31, 1) ("htcpUnpackDetail: failed to unpack CACHE-HDRS\n");
 	htcpFreeDetail(d);
 	return NULL;
     }
-    buf += o;
-    sz -= o;
+    /* Add terminating null to ENTITY-HDRS */
+    *buf = '\0';
+    /* Set CACHE-HDRS */
+    buf += 2;
+    d->cache_hdrs = buf;
+    buf += l;
+    sz -= l;
+
     debug(31, 3) ("htcpUnpackDetail: %d bytes left\n", sz);
+    /* 
+     * Add terminating null to CACHE-HDRS. This is possible because we allocated 
+     * an extra byte when we received the packet. This will overwrite any following
+     * AUTH block.
+     */
+    *buf = '\0';
     return d;
 }
 
+static int
+htcpAccessCheck(acl_access * acl, htcpSpecifier * s, struct sockaddr_in *from)
+{
+    aclCheck_t checklist;
+    memset(&checklist, '\0', sizeof(checklist));
+    checklist.src_addr = from->sin_addr;
+    checklist.my_addr = no_addr;
+    checklist.request = s->request;
+    return aclCheckFast(acl, &checklist);
+}
+
 static void
 htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, struct sockaddr_in *from)
 {
     htcpStuff stuff;
-    char *pkt;
+    static char pkt[8192];
     HttpHeader hdr;
     MemBuf mb;
     Packer p;
@@ -597,16 +653,41 @@
 	httpHeaderClean(&hdr);
 	packerClean(&p);
     }
-    pkt = htcpBuildPacket(&stuff, &pktlen);
+    pktlen = htcpBuildPacket(pkt, sizeof(pkt), &stuff);
     safe_free(stuff.D.resp_hdrs);
     safe_free(stuff.D.entity_hdrs);
     safe_free(stuff.D.cache_hdrs);
-    if (pkt == NULL) {
+    if (!pktlen) {
 	debug(31, 0) ("htcpTstReply: htcpBuildPacket() failed\n");
 	return;
     }
     htcpSend(pkt, (int) pktlen, from);
-    xfree(pkt);
+}
+
+static void
+htcpClrReply(htcpDataHeader * dhdr, int purgeSucceeded, struct sockaddr_in *from)
+{
+    htcpStuff stuff;
+    static char pkt[8192];
+    ssize_t pktlen;
+
+    /* If dhdr->F1 == 0, no response desired */
+    if (dhdr->F1 == 0)
+	return;
+
+    memset(&stuff, '\0', sizeof(stuff));
+    stuff.op = HTCP_CLR;
+    stuff.rr = RR_RESPONSE;
+    stuff.f1 = 0;
+    stuff.response = purgeSucceeded ? 0 : 2;
+    debug(31, 3) ("htcpClrReply: response = %d\n", stuff.response);
+    stuff.msg_id = dhdr->msg_id;
+    pktlen = htcpBuildPacket(pkt, sizeof(pkt), &stuff);
+    if (pktlen == 0) {
+	debug(31, 0) ("htcpClrReply: htcpBuildPacket() failed\n");
+	return;
+    }
+    htcpSend(pkt, (int) pktlen, from);
 }
 
 static void
@@ -618,11 +699,9 @@
 static StoreEntry *
 htcpCheckHit(const htcpSpecifier * s)
 {
-    request_t *request;
-    method_t m = urlParseMethod(s->method);
+    request_t *request = s->request;
     StoreEntry *e = NULL, *hit = NULL;
     char *blk_end;
-    request = urlParse(m, s->uri);
     if (NULL == request) {
 	debug(31, 3) ("htcpCheckHit: NO; failed to parse URL\n");
 	return NULL;
@@ -648,11 +727,52 @@
     debug(31, 3) ("htcpCheckHit: YES!?\n");
     hit = e;
   miss:
-    requestDestroy(request);
     return hit;
 }
 
 static void
+htcpClrStoreEntry(StoreEntry * e)
+{
+    debug(31, 4) ("htcpClrStoreEntry: Clearing store for entry: %s\n", storeUrl(e));
+    storeRelease(e);
+}
+
+static int
+htcpClrStore(const htcpSpecifier * s)
+{
+    request_t *request = s->request;
+    char *blk_end;
+    StoreEntry *e = NULL;
+    int released;
+
+    if (request == NULL) {
+	debug(31, 3) ("htcpClrStore: failed to parse URL\n");
+	return -1;
+    }
+    /* Parse request headers */
+    blk_end = s->req_hdrs + strlen(s->req_hdrs);
+    if (!httpHeaderParse(&request->header, s->req_hdrs, blk_end)) {
+	debug(31, 2) ("htcpClrStore: failed to parse request headers\n");
+	return -1;
+    }
+    /* Lookup matching entries. This matches both GET and HEAD */
+    while ((e = storeGetPublicByRequest(request)) != NULL) {
+	if (e != NULL) {
+	    htcpClrStoreEntry(e);
+	    released++;
+	}
+    }
+
+    if (released) {
+	debug(31, 4) ("htcpClrStore: Cleared %d matching entries\n", released);
+	return 1;
+    } else {
+	debug(31, 4) ("htcpClrStore: No matching entry found\n");
+	return 0;
+    }
+}
+
+static void
 htcpHandleTst(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
 {
     debug(31, 3) ("htcpHandleTst: sz = %d\n", (int) sz);
@@ -667,10 +787,22 @@
 {
     htcpReplyData htcpReply;
     cache_key *key = NULL;
+    struct sockaddr_in *peer;
     htcpDetail *d = NULL;
     char *t;
+
+    key = queried_keys[hdr->msg_id % N_QUERIED_KEYS];
+    if (!key) {
+	debug(31, 2) ("htcpHandleTstResponse: No matching query id '%d' from '%s'\n", hdr->msg_id, inet_ntoa(from->sin_addr));
+	return;
+    }
+    peer = &queried_addr[hdr->msg_id % N_QUERIED_KEYS];
+    if (peer->sin_addr.s_addr != from->sin_addr.s_addr || peer->sin_port != from->sin_port) {
+	debug(31, 1) ("htcpHandleTstResponse: Unexpected response source %s\n", inet_ntoa(from->sin_addr));
+	return;
+    }
     if (hdr->F1 == 1) {
-	debug(31, 1) ("htcpHandleTstResponse: error condition, F1/MO == 1\n");
+	debug(31, 2) ("htcpHandleTstResponse: error condition, F1/MO == 1\n");
 	return;
     }
     memset(&htcpReply, '\0', sizeof(htcpReply));
@@ -716,7 +848,17 @@
 	return;
     s = htcpUnpackSpecifier(buf, sz);
     if (NULL == s) {
-	debug(31, 3) ("htcpHandleTstRequest: htcpUnpackSpecifier failed\n");
+	debug(31, 2) ("htcpHandleTstRequest: htcpUnpackSpecifier failed\n");
+	return;
+    }
+    if (!s->request) {
+	debug(31, 2) ("htcpHandleTstRequest: failed to parse request\n");
+	htcpFreeSpecifier(s);
+	return;
+    }
+    if (!htcpAccessCheck(Config.accessList.htcp, s, from)) {
+	debug(31, 2) ("htcpHandleTstRequest: Access denied\n");
+	htcpFreeSpecifier(s);
 	return;
     }
     debug(31, 3) ("htcpHandleTstRequest: %s %s %s\n",
@@ -744,6 +886,54 @@
 }
 
 static void
+htcpHandleClr(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from)
+{
+    /* buf[0/1] is reserved and reason */
+    int reason = buf[1] << 4;
+    debug(31, 3) ("htcpHandleClr: reason=%d\n", reason);
+    buf += 2;
+    sz -= 2;
+
+    /* buf should be a SPECIFIER */
+    htcpSpecifier *s;
+    if (sz == 0) {
+	debug(31, 4) ("htcpHandleClr: nothing to do\n");
+	return;
+    }
+    s = htcpUnpackSpecifier(buf, sz);
+    if (NULL == s) {
+	debug(31, 3) ("htcpHandleClr: htcpUnpackSpecifier failed\n");
+	return;
+    }
+    if (!htcpAccessCheck(Config.accessList.htcp_clr, s, from)) {
+	debug(31, 2) ("htcpHandleClr: Access denied\n");
+	htcpFreeSpecifier(s);
+	return;
+    }
+    debug(31, 5) ("htcpHandleClr: %s %s %s\n",
+	s->method,
+	s->uri,
+	s->version);
+    debug(31, 5) ("htcpHandleClr: request headers: %s\n", s->req_hdrs);
+
+    /* Release objects from cache
+     * analog to clientPurgeRequest in client_side.c
+     */
+    switch (htcpClrStore(s)) {
+    case 1:
+	htcpClrReply(hdr, 1, from);	/* hit */
+	break;
+    case 0:
+	htcpClrReply(hdr, 0, from);	/* miss */
+	break;
+    default:
+	break;
+    }
+
+    htcpFreeSpecifier(s);
+}
+
+static void
 htcpHandleData(char *buf, int sz, struct sockaddr_in *from)
 {
     htcpDataHeader hdr;
@@ -795,12 +985,10 @@
 	htcpHandleSet(&hdr, buf, sz, from);
 	break;
     case HTCP_CLR:
-	debug(31, 1) ("htcpHandleData: client %s, CLR not supported\n",
-	    inet_ntoa(from->sin_addr));
+	htcpHandleClr(&hdr, buf, sz, from);
 	break;
     default:
-	assert(0);
-	break;
+	return;
     }
 }
 
@@ -838,7 +1026,8 @@
     socklen_t flen = sizeof(struct sockaddr_in);
     memset(&from, '\0', flen);
     statCounter.syscalls.sock.recvfroms++;
-    len = recvfrom(fd, buf, 8192, 0, (struct sockaddr *) &from, &flen);
+    /* Receive up to 8191 bytes, leaving room for a null */
+    len = recvfrom(fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &from, &flen);
     debug(31, 3) ("htcpRecv: FD %d, %d bytes from %s:%d\n",
 	fd, len, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
     htcpHandle(buf, len, &from);
@@ -899,7 +1088,7 @@
 htcpQuery(StoreEntry * e, request_t * req, peer * p)
 {
     cache_key *save_key;
-    char *pkt;
+    static char pkt[8192];
     ssize_t pktlen;
     char vbuf[32];
     htcpStuff stuff;
@@ -929,17 +1118,17 @@
     httpHeaderClean(&hdr);
     packerClean(&pa);
     stuff.S.req_hdrs = mb.buf;
-    pkt = htcpBuildPacket(&stuff, &pktlen);
+    pktlen = htcpBuildPacket(pkt, sizeof(pkt), &stuff);
     memBufClean(&mb);
-    if (pkt == NULL) {
+    if (!pktlen) {
 	debug(31, 0) ("htcpQuery: htcpBuildPacket() failed\n");
 	return;
     }
     htcpSend(pkt, (int) pktlen, &p->in_addr);
     save_key = queried_keys[stuff.msg_id % N_QUERIED_KEYS];
     storeKeyCopy(save_key, e->hash.key);
+    queried_addr[stuff.msg_id % N_QUERIED_KEYS] = p->in_addr;
     debug(31, 3) ("htcpQuery: key (%p) %s\n", save_key, storeKeyText(save_key));
-    xfree(pkt);
 }
 
 /*  
Index: squid/src/protos.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/protos.h,v
retrieving revision 1.74.2.14
retrieving revision 1.74.2.15
diff -u -r1.74.2.14 -r1.74.2.15
--- squid/src/protos.h	29 May 2006 18:41:17 -0000	1.74.2.14
+++ squid/src/protos.h	31 May 2006 10:20:01 -0000	1.74.2.15
@@ -1,6 +1,6 @@
 
 /*
- * $Id: protos.h,v 1.74.2.14 2006/05/29 18:41:17 serassio Exp $
+ * $Id: protos.h,v 1.74.2.15 2006/05/31 10:20:01 serassio Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -135,15 +135,10 @@
 extern void clientdbFreeMemory(void);
 extern int clientdbEstablished(struct in_addr, int);
 
-extern void clientAccessCheck(void *);
-extern void clientAccessCheckDone(int, void *);
-extern int modifiedSince(StoreEntry *, request_t *);
 extern char *clientConstructTraceEcho(clientHttpRequest *);
-extern void clientPurgeRequest(clientHttpRequest *);
 extern int checkNegativeHit(StoreEntry *);
 extern void clientOpenListenSockets(void);
 extern void clientHttpConnectionsClose(void);
-extern StoreEntry *clientCreateStoreEntry(clientHttpRequest *, method_t, request_flags);
 extern int isTcpHit(log_type);
 
 extern int commSetNonBlocking(int fd);
Index: squid/src/structs.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/structs.h,v
retrieving revision 1.81.2.11
retrieving revision 1.81.2.12
diff -u -r1.81.2.11 -r1.81.2.12
--- squid/src/structs.h	30 May 2006 19:05:59 -0000	1.81.2.11
+++ squid/src/structs.h	31 May 2006 10:20:02 -0000	1.81.2.12
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.81.2.11 2006/05/30 19:05:59 serassio Exp $
+ * $Id: structs.h,v 1.81.2.12 2006/05/31 10:20:02 serassio Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -695,6 +695,10 @@
 	acl_access *reply;
 	acl_address *outgoing_address;
 	acl_tos *outgoing_tos;
+#if USE_HTCP
+	acl_access *htcp;
+	acl_access *htcp_clr;
+#endif
     } accessList;
     acl_deny_info_list *denyInfoList;
     struct _authConfig {
