---------------------
PatchSet 1900 
Date: 2005/09/29 18:00:44
Author: dwsquid
Branch: squid3-icap
Tag: (none) 
Log:
Starting to make ICAP service selection work with icap_access configuration

Members: 
	src/ICAPAnchor.cc:1.1.2.28->1.1.2.29 
	src/ICAPAnchor.h:1.1.2.8->1.1.2.9 
	src/ICAPClient.cc:1.1.2.7->1.1.2.8 
	src/ICAPClient.h:1.1.2.6->1.1.2.7 
	src/ICAPClientSideHook.cc:1.1.2.6->1.1.2.7 
	src/ICAPConfig.cc:1.1.2.3->1.1.2.4 
	src/ICAPConfig.h:1.1.2.3->1.1.2.4 
	src/ICAPServiceRep.cc:1.1.2.4->1.1.2.5 
	src/ICAPServiceRep.h:1.1.2.4->1.1.2.5 
	src/ICAPXaction.cc:1.1.2.33->1.1.2.34 
	src/ICAPXaction.h:1.1.2.18->1.1.2.19 
	src/client_side_request.cc:1.34.4.7->1.34.4.8 
	src/http.cc:1.49.2.32->1.49.2.33 
	src/http.h:1.11.4.11->1.11.4.12 

Index: squid3/src/ICAPAnchor.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPAnchor.cc,v
retrieving revision 1.1.2.28
retrieving revision 1.1.2.29
diff -u -r1.1.2.28 -r1.1.2.29
--- squid3/src/ICAPAnchor.cc	18 Sep 2005 04:12:42 -0000	1.1.2.28
+++ squid3/src/ICAPAnchor.cc	29 Sep 2005 18:00:44 -0000	1.1.2.29
@@ -8,6 +8,7 @@
 #include "HttpReply.h"
 #include "ICAPAnchor.h"
 #include "ICAPClient.h"
+#include "ICAPServiceRep.h"
 
 #include "LeakFinder.h"
 
@@ -15,9 +16,10 @@
 
 extern LeakFinder *leaky;
 
-ICAPAnchor::ICAPAnchor(): httpState(NULL), virgin(NULL), adapted(NULL)
+ICAPAnchor::ICAPAnchor(ICAPServiceRep::Pointer aService): service(aService), httpState(NULL), virgin(NULL), adapted(NULL)
 {
     debug(93,5)("ICAPAnchor constructed, this=%p\n", this);
+    debug(0,0)("ICAPAnchor constructed, service=%p\n", service.getRaw());
 }
 
 ICAPAnchor::~ICAPAnchor()
@@ -31,6 +33,10 @@
 
     if (adapted != NULL)
         freeAdapted();
+
+    debug(0,0)("NULLing ICAPAnchor:service\n");
+
+    service = NULL;
 }
 
 void ICAPAnchor::startRespMod(HttpStateData *anHttpState, HttpRequest *request, HttpReply *reply)
@@ -55,7 +61,7 @@
     adapted->data->cause = request; // should not hurt
 #else
 
-    ICAPInitXaction(virgin, adapted);
+    ICAPInitXaction(service, virgin, adapted);
 #endif
 
     virgin->sendSourceStart(); // we may have virgin data to provide
Index: squid3/src/ICAPAnchor.h
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPAnchor.h,v
retrieving revision 1.1.2.8
retrieving revision 1.1.2.9
diff -u -r1.1.2.8 -r1.1.2.9
--- squid3/src/ICAPAnchor.h	31 Aug 2005 20:03:39 -0000	1.1.2.8
+++ squid3/src/ICAPAnchor.h	29 Sep 2005 18:00:44 -0000	1.1.2.9
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ICAPAnchor.h,v 1.1.2.8 2005/08/31 20:03:39 dwsquid Exp $
+ * $Id: ICAPAnchor.h,v 1.1.2.9 2005/09/29 18:00:44 dwsquid Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -37,6 +37,7 @@
 #include "MsgPipe.h"
 #include "MsgPipeSource.h"
 #include "MsgPipeSink.h"
+#include "ICAPServiceRep.h"
 
 /* The ICAP Anchor implements message pipe sink and source interfaces.  It
  * helps HttpStateData to marshall the incoming/virgin HTTP message (being
@@ -54,7 +55,7 @@
 {
 
 public:
-    ICAPAnchor();
+    ICAPAnchor(ICAPServiceRep::Pointer);
     virtual ~ICAPAnchor();
 
     // synchronous calls called by HttpStateData
@@ -75,6 +76,7 @@
     virtual void noteSourceAbort(MsgPipe *p);
 
 public:
+    ICAPServiceRep::Pointer service;
     HttpStateData *httpState;
     MsgPipe::Pointer virgin;
     MsgPipe::Pointer adapted;
Index: squid3/src/ICAPClient.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPClient.cc,v
retrieving revision 1.1.2.7
retrieving revision 1.1.2.8
diff -u -r1.1.2.7 -r1.1.2.8
--- squid3/src/ICAPClient.cc	31 Aug 2005 20:03:39 -0000	1.1.2.7
+++ squid3/src/ICAPClient.cc	29 Sep 2005 18:00:44 -0000	1.1.2.8
@@ -18,11 +18,11 @@
 {}
 
 // initialize ICAP-specific ends of message pipes
-void ICAPInitXaction(MsgPipe::Pointer virgin, MsgPipe::Pointer adapted)
+void ICAPInitXaction(ICAPServiceRep::Pointer service, MsgPipe::Pointer virgin, MsgPipe::Pointer adapted)
 {
     ICAPXaction::Pointer x = new ICAPXaction;
     debugs(93,5, "ICAPInitXaction: " << x.getRaw());
-    x->init(virgin, adapted, x);
+    x->init(service, virgin, adapted, x);
     // if we want to do something to the transaction after it is done,
     // we need to keep a pointer to it
 }
Index: squid3/src/ICAPClient.h
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPClient.h,v
retrieving revision 1.1.2.6
retrieving revision 1.1.2.7
diff -u -r1.1.2.6 -r1.1.2.7
--- squid3/src/ICAPClient.h	31 Aug 2005 20:03:39 -0000	1.1.2.6
+++ squid3/src/ICAPClient.h	29 Sep 2005 18:00:44 -0000	1.1.2.7
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ICAPClient.h,v 1.1.2.6 2005/08/31 20:03:39 dwsquid Exp $
+ * $Id: ICAPClient.h,v 1.1.2.7 2005/09/29 18:00:44 dwsquid Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -45,7 +45,7 @@
 // let ICAP initialize ICAP-specific ends of message pipes
 
 class MsgPipe;
-extern void ICAPInitXaction(MsgPipe::Pointer virgin, MsgPipe::Pointer adapted);
+extern void ICAPInitXaction(ICAPServiceRep::Pointer, MsgPipe::Pointer virgin, MsgPipe::Pointer adapted);
 
 // recommended initial size and max capacity for MsgPipe buffer
 enum { ICAPMsgPipeBufSizeMin = (4*1024), ICAPMsgPipeBufSizeMax = SQUID_TCP_SO_RCVBUF };
Index: squid3/src/ICAPClientSideHook.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPClientSideHook.cc,v
retrieving revision 1.1.2.6
retrieving revision 1.1.2.7
diff -u -r1.1.2.6 -r1.1.2.7
--- squid3/src/ICAPClientSideHook.cc	21 Sep 2005 20:36:07 -0000	1.1.2.6
+++ squid3/src/ICAPClientSideHook.cc	29 Sep 2005 18:00:44 -0000	1.1.2.7
@@ -7,6 +7,7 @@
 #include "MsgPipeSink.h"
 #include "HttpRequest.h"
 #include "ICAPClientSideHook.h"
+#include "ICAPServiceRep.h"
 #include "ICAPClient.h"
 
 #include "LeakFinder.h"
@@ -51,7 +52,8 @@
     leakTouch(adapted.getRaw(), leaky);
     adapted->sink = this;
 
-    ICAPInitXaction(virgin, adapted);
+    fatal("fix following ICAPInitXaction() call");
+    ICAPInitXaction(NULL, virgin, adapted);
 
     virgin->sendSourceStart(); // we may have virgin data to provide
     adapted->sendSinkNeed();   // we want adapted response, eventially
Index: squid3/src/ICAPConfig.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPConfig.cc,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -u -r1.1.2.3 -r1.1.2.4
--- squid3/src/ICAPConfig.cc	27 Sep 2005 20:40:57 -0000	1.1.2.3
+++ squid3/src/ICAPConfig.cc	29 Sep 2005 18:00:44 -0000	1.1.2.4
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ICAPConfig.cc,v 1.1.2.3 2005/09/27 20:40:57 dwsquid Exp $
+ * $Id: ICAPConfig.cc,v 1.1.2.4 2005/09/29 18:00:44 dwsquid Exp $
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
  * ----------------------------------------------------------
@@ -38,34 +38,43 @@
 #include "ACL.h"
 #include "Store.h"
 #include "List.h"
+#include "Array.h"	// really Vector
 #include "ICAPConfig.h"
 #include "ICAPServiceRep.h"
+#include "HttpRequest.h"
 
 ICAPConfig TheICAPConfig;
 
+ICAPServiceRep::Pointer
+ICAPConfig::findService(const String& key)
+{
+    Vector<ICAPServiceRep::Pointer>::iterator iter = services.begin();
+
+    while (iter != TheICAPConfig.services.end()) {
+        if (iter->getRaw()->key == key)
+            return *iter;
+
+        ++iter;
+    }
+
+    return NULL;
+}
+
 int
 ICAPClass::prepare()
 {
     int found = 0;
-    List<ICAPServiceRep> **Tail;
-    List<ICAPServiceRep> *service_iter;
     wordlist *iter;
 
     ConfigParser::ParseString(&key);
     ConfigParser::ParseWordList(&service_names);
 
     for (iter = service_names; iter; iter = iter->next) {
-        for (service_iter = TheICAPConfig.services; service_iter; service_iter = service_iter->next) {
-            if (!service_iter->element.key.cmp(iter->key)) {
-                for (Tail = &services; *Tail; Tail = &((*Tail)->next))
-
-                    ;
-                List<ICAPServiceRep> * q = new List<ICAPServiceRep>(service_iter->element);
-
-                *(Tail) = q;
+        ICAPServiceRep::Pointer match = TheICAPConfig.findService(iter->key);
 
-                found = 1;
-            }
+        if (match != NULL) {
+            found = 1;
+            services += match;
         }
     }
 
@@ -98,19 +107,83 @@
     return found;
 };
 
+// ================================================================================ //
+
+CBDATA_CLASS_INIT(ICAPAccessCheck);
+
+ICAPAccessCheck::ICAPAccessCheck(ICAPServiceRep::IcapMethod aMethod,
+                                 ICAPServiceRep::IcapVectPoint aPoint,
+                                 HttpRequest *aReq,
+                                 HttpReply *aRep,
+                                 ICAPAccessCheckCallback *aCallback,
+                                 void *aCallbackData)
+{
+    method = aMethod;
+    point = aPoint;
+    req = requestLink(aReq);
+    rep = aRep;
+    callback = aCallback;
+    callback_data = aCallbackData;
+    match = NULL;
+}
+
+ICAPAccessCheck::~ICAPAccessCheck()
+{
+    requestUnlink(req);
+}
+
+void
+ICAPAccessCheck::check()
+{
+    debug(0,0)("ICAPAccessCheck::check\n");
+    Vector<ICAPServiceRep::Pointer>::iterator i;
+
+    for (i = TheICAPConfig.services.begin(); i != TheICAPConfig.services.end(); ++i) {
+        if (method != i->getRaw()->method)
+            continue;
+
+        if (point != i->getRaw()->point)
+            continue;
+
+        debug(0,0)("ICAPAccessCheck::check: found a matching service\n");
+
+        match = *i;
+
+        eventAdd("ICAPAccessCheckCallbackWrapper",
+                 ICAPAccessCheckCallbackWrapper,
+                 this,
+                 0.0,
+                 0,
+                 1);
+    }
+}
+
+void
+ICAPAccessCheck::ICAPAccessCheckCallbackWrapper(void *data)
+{
+    debug(0,0)("ICAPAccessCheckCallbackWrapper\n");
+    ICAPAccessCheck *ac = (ICAPAccessCheck*)data;
+    ac->do_callback();
+}
+
+void
+ICAPAccessCheck::do_callback()
+{
+    debug(0,0)("ICAPAccessCheck::do_callback\n");
+    callback(match, callback_data);
+    match = NULL;
+}
+
+
+// ================================================================================ //
+
 void
 ICAPConfig::parseICAPService()
 {
-    List<ICAPServiceRep> **Tail;
     ICAPServiceRep *S = new ICAPServiceRep();
 
     if (S->parseConfigLine()) {
-        for (Tail = &services; *Tail; Tail = &((*Tail)->next))
-
-            ;
-        List<ICAPServiceRep> * q = new List<ICAPServiceRep>(*S);
-
-        *(Tail) = q;
+        services += S;
     } else {
         delete S;
     }
@@ -121,18 +194,18 @@
 void
 ICAPConfig::freeICAPService()
 {
-    delete services;
+    services.clean();
 };
 
 void
 ICAPConfig::dumpICAPService(StoreEntry *entry, const char *name)
 {
-    List<ICAPServiceRep> *data = services;
+    Vector<ICAPServiceRep::Pointer>::iterator i = services.begin();
 
-    while (data != NULL) {
-        ICAPServiceRep *r = &data->element;
+    while (i != services.end()) {
+        ICAPServiceRep *r = i->getRaw();
         storeAppendPrintf(entry, "%s %s_%s %s %d %s\n", name, r->key.buf(), r->methodStr(), r->vectPointStr(), r->bypass, r->uri.buf());
-        data = data->next;
+        ++i;
     }
 };
 
@@ -223,6 +296,6 @@
 ICAPConfig::~ICAPConfig()
 {
     delete classes;
-    delete services;
+    services.clean();
     delete accesses;
 };
Index: squid3/src/ICAPConfig.h
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPConfig.h,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -u -r1.1.2.3 -r1.1.2.4
--- squid3/src/ICAPConfig.h	27 Sep 2005 20:40:57 -0000	1.1.2.3
+++ squid3/src/ICAPConfig.h	29 Sep 2005 18:00:44 -0000	1.1.2.4
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ICAPConfig.h,v 1.1.2.3 2005/09/27 20:40:57 dwsquid Exp $
+ * $Id: ICAPConfig.h,v 1.1.2.4 2005/09/29 18:00:44 dwsquid Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -37,13 +37,12 @@
 #define SQUID_ICAPCONFIG_H
 
 #include "List.h"
+#include "ICAPServiceRep.h"
 
 class acl_access;
 
 class ICAPConfig;
 
-class ICAPServiceRep;
-
 class ICAPClass
 {
 
@@ -51,9 +50,9 @@
     char *key;
     wordlist *service_names;
 
-    List<ICAPServiceRep> *services;
+    Vector<ICAPServiceRep::Pointer> services;
 
-    ICAPClass() : key(NULL), service_names(NULL), services(NULL) {};
+    ICAPClass() : key(NULL), service_names(NULL) {};
 
     int prepare();
 };
@@ -78,6 +77,33 @@
 
 };
 
+class ICAPAccessCheck
+{
+
+public:
+    typedef void ICAPAccessCheckCallback(ICAPServiceRep::Pointer match, void *data);
+    ICAPAccessCheck(ICAPServiceRep::IcapMethod, ICAPServiceRep::IcapVectPoint, HttpRequest *, HttpReply *, ICAPAccessCheckCallback *, void *);
+    ~ICAPAccessCheck();
+
+private:
+    ICAPServiceRep::IcapMethod method;
+    ICAPServiceRep::IcapVectPoint point;
+    HttpRequest *req;
+    HttpReply *rep;
+    ICAPAccessCheckCallback *callback;
+    void *callback_data;
+
+    ICAPServiceRep::Pointer match;
+    void do_callback();
+
+public:
+    void check();
+    static void ICAPAccessCheckCallbackWrapper(void*);
+
+private:
+    CBDATA_CLASS2(ICAPAccessCheck);
+};
+
 class ICAPConfig
 {
 
@@ -91,17 +117,18 @@
     int auth_user;
     char *auth_scheme;
 
-    List<ICAPServiceRep> *services;
+    Vector<ICAPServiceRep::Pointer> services;
     List<ICAPClass> *classes;
     List<ICAPAccess> *accesses;
 
-    ICAPConfig() : services(NULL), classes(NULL), accesses(NULL) {};
+    ICAPConfig() : classes(NULL), accesses(NULL) {};
 
     ~ICAPConfig();
 
     void parseICAPService(void);
     void freeICAPService(void);
     void dumpICAPService(StoreEntry *, const char *);
+    ICAPServiceRep::Pointer findService(const String&);
 
     void parseICAPClass(void);
     void freeICAPClass(void);
Index: squid3/src/ICAPServiceRep.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPServiceRep.cc,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -u -r1.1.2.4 -r1.1.2.5
--- squid3/src/ICAPServiceRep.cc	27 Sep 2005 20:40:57 -0000	1.1.2.4
+++ squid3/src/ICAPServiceRep.cc	29 Sep 2005 18:00:44 -0000	1.1.2.5
@@ -9,7 +9,10 @@
 
 ICAPServiceRep::~ICAPServiceRep()
 {
+    debug(0,0)("~ICAPServiceRep destructor called\n");
+    debug(0,0)("~ICAPServiceRep deleting opts\n");
     delete opts;
+    debug(0,0)("~ICAPServiceRep done\n");
 }
 
 const char *
@@ -124,7 +127,7 @@
     }
 
     int len = e - s;
-    host.limitInit(s, len + 1);
+    host.limitInit(s, len);
     s = e;
 
     if (have_port) {
Index: squid3/src/ICAPServiceRep.h
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPServiceRep.h,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -u -r1.1.2.4 -r1.1.2.5
--- squid3/src/ICAPServiceRep.h	27 Sep 2005 20:40:57 -0000	1.1.2.4
+++ squid3/src/ICAPServiceRep.h	29 Sep 2005 18:00:44 -0000	1.1.2.5
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ICAPServiceRep.h,v 1.1.2.4 2005/09/27 20:40:57 dwsquid Exp $
+ * $Id: ICAPServiceRep.h,v 1.1.2.5 2005/09/29 18:00:44 dwsquid Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -43,10 +43,12 @@
 
 class ICAPOptions;
 
-class ICAPServiceRep
+class ICAPServiceRep : public RefCountable
 {
 
 public:
+    typedef RefCount<ICAPServiceRep> Pointer;
+
     ICAPServiceRep();
     ~ICAPServiceRep();
     bool parseConfigLine();
Index: squid3/src/ICAPXaction.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPXaction.cc,v
retrieving revision 1.1.2.33
retrieving revision 1.1.2.34
diff -u -r1.1.2.33 -r1.1.2.34
--- squid3/src/ICAPXaction.cc	29 Sep 2005 05:17:21 -0000	1.1.2.33
+++ squid3/src/ICAPXaction.cc	29 Sep 2005 18:00:44 -0000	1.1.2.34
@@ -104,8 +104,8 @@
     memset(this, sizeof(*this), 0);
 }
 
-ICAPXaction::ICAPXaction(): self(NULL), virgin(NULL), adapted(NULL),
-        icapReply(NULL), service(NULL), connection(-1),
+ICAPXaction::ICAPXaction(): self(NULL), service(NULL), virgin(NULL), adapted(NULL),
+        icapReply(NULL), connection(-1),
         commBuf(NULL), reader(NULL), writer(NULL), closer(NULL),
         bodyParser(NULL),
         notify(notifyUnknown)
@@ -117,12 +117,13 @@
     doStop();
 }
 
-void ICAPXaction::init(MsgPipe::Pointer aVirgin, MsgPipe::Pointer anAdapted, Pointer &aSelf)
+void ICAPXaction::init(ICAPServiceRep::Pointer aService, MsgPipe::Pointer aVirgin, MsgPipe::Pointer anAdapted, Pointer &aSelf)
 {
     assert(!self.getRaw() && !virgin.getRaw() && !adapted.getRaw());
     assert(aSelf.getRaw() && aVirgin.getRaw() && anAdapted.getRaw());
 
     self = aSelf;
+    service = aService;
     virgin = aVirgin;
     adapted = anAdapted;
 
@@ -159,7 +160,6 @@
 {
     ICAPXaction_Enter(noteSourceStart);
 
-    pickService();
     openConnection();
     // put nothing here as openConnection calls commConnectStart
     // and that may call us back without waiting for the next select loop
@@ -188,6 +188,7 @@
                    &ICAPXaction_noteCommTimeout, this);
     closer = &ICAPXaction_noteCommClose;
     comm_add_close_handler(connection, closer, this);
+debug(0,0)("ICAPXaction::openConnection() to %s %d\n", service->host.buf(), service->port);
     commConnectStart(connection, service->host.buf(), service->port,
                      &ICAPXaction_noteCommConnected, this);
 }
@@ -602,11 +603,6 @@
     ICAPXaction_Exit(noteSinkAbort);
 }
 
-void ICAPXaction::pickService()
-{
-    assert(false);
-}
-
 void ICAPXaction::mustStop(Notify who)
 {
     Must(state.inCall); // otherwise nobody will call doStop()
Index: squid3/src/ICAPXaction.h
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPXaction.h,v
retrieving revision 1.1.2.18
retrieving revision 1.1.2.19
diff -u -r1.1.2.18 -r1.1.2.19
--- squid3/src/ICAPXaction.h	29 Sep 2005 05:17:21 -0000	1.1.2.18
+++ squid3/src/ICAPXaction.h	29 Sep 2005 18:00:44 -0000	1.1.2.19
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ICAPXaction.h,v 1.1.2.18 2005/09/29 05:17:21 rousskov Exp $
+ * $Id: ICAPXaction.h,v 1.1.2.19 2005/09/29 18:00:44 dwsquid Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -64,7 +64,7 @@
     virtual ~ICAPXaction();
 
     // called by ICAPClient
-    void init(MsgPipe::Pointer aVirgin, MsgPipe::Pointer anAdapted, Pointer &aSelf);
+    void init(ICAPServiceRep::Pointer, MsgPipe::Pointer aVirgin, MsgPipe::Pointer anAdapted, Pointer &aSelf);
     void ownerAbort();
 
     // pipe source methods; called by Anchor while receiving the adapted msg
@@ -103,8 +103,6 @@
     void maybeAllocateHttpMsg();
     bool expectVirginBody() const;
 
-    void pickService();
-
     bool done() const;
 
     typedef enum { notifyUnknown, notifyNone, notifyService, notifyHttp,
@@ -129,12 +127,12 @@
     bool gotEncapsulated(const char *section) const;
 
     Pointer self;
+    ICAPServiceRep::Pointer service;
     MsgPipe::Pointer virgin;
     MsgPipe::Pointer adapted;
 
     HttpReply *icapReply;
 
-    ICAPServiceRep *service;
     int connection;     // FD of the ICAP server connection
 
     /*
Index: squid3/src/client_side_request.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/client_side_request.cc,v
retrieving revision 1.34.4.7
retrieving revision 1.34.4.8
diff -u -r1.34.4.7 -r1.34.4.8
--- squid3/src/client_side_request.cc	21 Sep 2005 20:33:38 -0000	1.34.4.7
+++ squid3/src/client_side_request.cc	29 Sep 2005 18:00:44 -0000	1.34.4.8
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side_request.cc,v 1.34.4.7 2005/09/21 20:33:38 dwsquid Exp $
+ * $Id: client_side_request.cc,v 1.34.4.8 2005/09/29 18:00:44 dwsquid Exp $
  * 
  * DEBUG: section 85    Client-side Request Routines
  * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c)
@@ -985,7 +985,7 @@
         return;
     }
 
-#if ICAP_CLIENT
+#if ICAP_CLIENT && 0
     if (!calloutContext->icap_reqmod_done) {
         calloutContext->icap_reqmod_done = 1;
 
Index: squid3/src/http.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/http.cc,v
retrieving revision 1.49.2.32
retrieving revision 1.49.2.33
diff -u -r1.49.2.32 -r1.49.2.33
--- squid3/src/http.cc	28 Sep 2005 21:47:23 -0000	1.49.2.32
+++ squid3/src/http.cc	29 Sep 2005 18:00:44 -0000	1.49.2.33
@@ -1,6 +1,6 @@
 
 /*
- * $Id: http.cc,v 1.49.2.32 2005/09/28 21:47:23 dwsquid Exp $
+ * $Id: http.cc,v 1.49.2.33 2005/09/29 18:00:44 dwsquid Exp $
  *
  * DEBUG: section 11    Hypertext Transfer Protocol (HTTP)
  * AUTHOR: Harvest Derived
@@ -54,6 +54,7 @@
 #endif
 #if ICAP_CLIENT
 #include "ICAPAnchor.h"
+#include "ICAPConfig.h"
 #endif
 
 CBDATA_TYPE(HttpStateData);
@@ -73,6 +74,9 @@
 static void copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, String strConnection, HttpRequest * request, HttpRequest * orig_request,
         HttpHeader * hdr_out, int we_do_ranges, http_state_flags);
 static int decideIfWeDoRanges (HttpRequest * orig_request);
+#if ICAP_CLIENT
+static void icapAclCheckDoneWrapper(ICAPServiceRep::Pointer service, void *data);
+#endif
 
 static void
 httpStateFree(int fd, void *data)
@@ -740,26 +744,10 @@
      */
 
 #if ICAP_CLIENT
-    /*
-     * One reason to start ICAP here is so that we know the size
-     * of the ICAP pipe buffer for the first HTTP reply read
-     * from the network.
-     */
 
-    if (doIcap() < 0) {
-        /*
-         * XXX Maybe instead of an error page we should
-         * handle the reply normally (without ICAP).
-         */
-        ErrorState *err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
-        err->xerrno = errno;
-        err->request = requestLink(orig_request);
-        errorAppendEntry(entry, err);
-        comm_close(fd);
-        ctx_exit(ctx);
-        return;
-    } else {
-        icap->startRespMod(this, request, reply);
+    if (icap_access_check = new ICAPAccessCheck(ICAPServiceRep::respmod, ICAPServiceRep::precache, request, reply, icapAclCheckDoneWrapper, this)) {
+        icap_access_check->check();
+	icapAccessCheckPending = true;
         ctx_exit(ctx);
         return;
     }
@@ -1111,9 +1099,11 @@
 void
 HttpStateData::writeReplyBody(const char *data, int len)
 {
+debug(0,0)("HttpStateData::writeReplyBody() called\n");
 #if ICAP_CLIENT
 
     if (icap)  {
+debug(0,0)("HttpStateData::writeReplyBody sending %d bytes to ICAP\n", len);
         icap->sendMoreData (StoreIOBuffer(len, 0, (char*)data));
         return;
     }
@@ -1137,12 +1127,16 @@
 void
 HttpStateData::processReplyBody()
 {
+debug(0,0)("HttpStateData::processReplyBody() called\n");
     if (!flags.headers_parsed) {
         flags.do_next_read = 1;
         maybeReadData();
         return;
     }
 
+    if (icapAccessCheckPending)
+	return;
+
     /*
      * At this point the reply headers have been parsed and consumed.
      * That means header content has been removed from readBuf and
@@ -1982,17 +1976,54 @@
 }
 
 #if ICAP_CLIENT
+
+static void
+icapAclCheckDoneWrapper(ICAPServiceRep::Pointer service, void *data)
+{
+    HttpStateData *http = (HttpStateData *)data;
+    http->icapAclCheckDone(service);
+}
+
+void
+HttpStateData::icapAclCheckDone(ICAPServiceRep::Pointer service)
+{
+    icapAccessCheckPending = false;
+    if (service == NULL) {
+        // handle case where no service is selected;
+        assert(false);
+        return;
+    }
+
+    debug(0,0)("icapAclCheckDone: service=%p\n", service.getRaw());
+
+    if (doIcap(service) < 0) {
+        /*
+         * XXX Maybe instead of an error page we should
+         * handle the reply normally (without ICAP).
+         */
+        ErrorState *err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
+        err->xerrno = errno;
+        err->request = requestLink(orig_request);
+        errorAppendEntry(entry, err);
+        comm_close(fd);
+        return;
+    }
+
+    icap->startRespMod(this, request, reply);
+    processReplyBody();
+}
+
 /*
  * Initiate an ICAP transaction.  Return 0 if all is well, or -1 upon error.
  * Caller will handle error condition by generating a Squid error message
  * or take other action.
  */
 int
-HttpStateData::doIcap()
+HttpStateData::doIcap(ICAPServiceRep::Pointer service)
 {
     debug(11,5)("HttpStateData::doIcap() called\n");
     assert(NULL == icap);
-    icap = new ICAPAnchor;
+    icap = new ICAPAnchor(service);
     (void) cbdataReference(icap);
     return 0;
 }
Index: squid3/src/http.h
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/http.h,v
retrieving revision 1.11.4.11
retrieving revision 1.11.4.12
diff -u -r1.11.4.11 -r1.11.4.12
--- squid3/src/http.h	28 Sep 2005 21:47:23 -0000	1.11.4.11
+++ squid3/src/http.h	29 Sep 2005 18:00:44 -0000	1.11.4.12
@@ -1,6 +1,6 @@
 
 /*
- * $Id: http.h,v 1.11.4.11 2005/09/28 21:47:23 dwsquid Exp $
+ * $Id: http.h,v 1.11.4.12 2005/09/29 18:00:44 dwsquid Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -36,9 +36,12 @@
 
 #include "StoreIOBuffer.h"
 #include "comm.h"
+#include "ICAPServiceRep.h"
 
 class ICAPAnchor;
 
+class ICAPAccessCheck;
+
 class HttpStateData
 {
 
@@ -76,10 +79,13 @@
     MemBuf *readBuf;
     bool ignoreCacheControl;
     bool surrogateNoStore;
+    bool icapAccessCheckPending;
     void processSurrogateControl(HttpReply *);
 #if ICAP_CLIENT
 
     ICAPAnchor *icap;
+    ICAPAccessCheck *icap_access_check;
+    void icapAclCheckDone(ICAPServiceRep::Pointer);
 #endif
 
     /*
@@ -111,7 +117,7 @@
     void writeReplyBody(const char *data, int len);
 #if ICAP_CLIENT
 
-    int doIcap();
+    int doIcap(ICAPServiceRep::Pointer);
 #endif
 };
 
