--------------------- PatchSet 2104 Date: 2005/11/03 21:36:45 Author: dwsquid Branch: squid3-icap Tag: (none) Log: These changes make ICAP actually call ACL functions as given by the icap_access rules. Note that I removed (disabled) the ICAPAccess class and attached the access_list to ICAPClass instead. This makes the code a little simpler. It also means that ICAP services/classes will be evaluated in the order of the icap_class lines, rather than the icap_access lines. Members: src/ICAPConfig.cc:1.1.2.10->1.1.2.11 src/ICAPConfig.h:1.1.2.5->1.1.2.6 Index: squid3/src/ICAPConfig.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPConfig.cc,v retrieving revision 1.1.2.10 retrieving revision 1.1.2.11 diff -u -r1.1.2.10 -r1.1.2.11 --- squid3/src/ICAPConfig.cc 17 Oct 2005 23:15:49 -0000 1.1.2.10 +++ squid3/src/ICAPConfig.cc 3 Nov 2005 21:36:45 -0000 1.1.2.11 @@ -1,6 +1,6 @@ /* - * $Id: ICAPConfig.cc,v 1.1.2.10 2005/10/17 23:15:49 rousskov Exp $ + * $Id: ICAPConfig.cc,v 1.1.2.11 2005/11/03 21:36:45 dwsquid Exp $ * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- @@ -37,11 +37,11 @@ #include "ConfigParser.h" #include "ACL.h" #include "Store.h" -#include "List.h" #include "Array.h" // really Vector #include "ICAPConfig.h" #include "ICAPServiceRep.h" #include "HttpRequest.h" +#include "ACLChecklist.h" ICAPConfig TheICAPConfig; @@ -50,7 +50,7 @@ { Vector::iterator iter = services.begin(); - while (iter != TheICAPConfig.services.end()) { + while (iter != services.end()) { if (iter->getRaw()->key == key) return *iter; @@ -60,10 +60,26 @@ return NULL; } +ICAPClass * +ICAPConfig::findClass(const String& key) +{ + Vector::iterator iter = classes.begin(); + + while (iter != classes.end()) { + if ((*iter)->key == key) + return *iter; + + ++iter; + } + + return NULL; +} + int ICAPClass::prepare() { int found = 0; + wordlist *service_names = NULL; wordlist *iter; ConfigParser::ParseString(&key); @@ -81,32 +97,6 @@ return found; }; -int -ICAPAccess::prepare() -{ - int found = 0; - - ConfigParser::ParseString(&key); - - List *data = TheICAPConfig.classes; - - while (data != NULL) { - if (!strcmp(data->element.key, key)) { - aclass =& data->element; - found = 1; - break; - } - - data = data->next; - } - - if (found) { - aclParseAccessLine(&(this->access)); - } - - return found; -}; - // ================================================================================ // CBDATA_CLASS_INIT(ICAPAccessCheck); @@ -124,7 +114,9 @@ rep = aRep; callback = aCallback; callback_data = aCallbackData; - match = NULL; + candidateClasses.clean(); + matchedClass.clean(); + acl_checklist = NULL; } ICAPAccessCheck::~ICAPAccessCheck() @@ -132,41 +124,87 @@ requestUnlink(req); } +/* + * Walk the ICAPAccess list and find all classes that have at least + * one service with matching method and vectoring point. + */ void ICAPAccessCheck::check() { debug(93,3)("ICAPAccessCheck::check\n"); - Vector::iterator i; + Vector::iterator ci; - match = NULL; + for (ci = TheICAPConfig.classes.begin(); ci != TheICAPConfig.classes.end(); ++ci) { - for (i = TheICAPConfig.services.begin(); i != TheICAPConfig.services.end(); ++i) { - if (method != i->getRaw()->method) - continue; + ICAPClass *theClass = *ci; + + Vector::iterator si; + + for (si = theClass->services.begin(); si != theClass->services.end(); ++si) { + ICAPServiceRep *theService = si->getRaw(); + + if (method != theService->method) + continue; + + if (point != theService->point) + continue; + + debug(93,1)("ICAPAccessCheck::check: class '%s' has candidate service '%s'\n", theClass->key.buf(), theService->key.buf()); + + candidateClasses += theClass->key; - if (point != i->getRaw()->point) + break; + } + } + + checkCandidates(); +} + +void +ICAPAccessCheck::checkCandidates() +{ + while (!candidateClasses.empty()) { + // It didn't really match yet, but we use the name anyway. + matchedClass = candidateClasses.shift(); + ICAPClass *theClass = TheICAPConfig.findClass(matchedClass); + + if (theClass == NULL) + // class apparently went away (reconfigure) continue; - debug(93,3)("ICAPAccessCheck::check: found a matching service\n"); + // XXX we don't have access to conn->rfc931 here. + acl_checklist = aclChecklistCreate(theClass->accessList, req, dash_str); - match = *i; + acl_checklist->nonBlockingCheck(ICAPAccessCheckCallbackWrapper, this); - break; + return; } - eventAdd("ICAPAccessCheckCallbackWrapper", - ICAPAccessCheckCallbackWrapper, - this, - 0.0, - 0, - 1); + /* + * when there are no canidates, set matchedClass to NULL string and call the + * wrapper with answer = 1 + */ + debug(93,1)("ICAPAccessCheck::check: NO candidates or matches found\n"); + + matchedClass.clean(); + + ICAPAccessCheckCallbackWrapper(1, this); + + return; } void -ICAPAccessCheck::ICAPAccessCheckCallbackWrapper(void *data) +ICAPAccessCheck::ICAPAccessCheckCallbackWrapper(int answer, void *data) { - debug(93,3)("ICAPAccessCheckCallbackWrapper\n"); + debug(93,1)("ICAPAccessCheckCallbackWrapper\n"); + debug(93,1)("ICAPAccessCheckCallbackWrapper: answer=%d\n", answer); ICAPAccessCheck *ac = (ICAPAccessCheck*)data; + + if (!answer) { + ac->checkCandidates(); + return; + } + ac->do_callback(); delete ac; } @@ -175,8 +213,32 @@ ICAPAccessCheck::do_callback() { debug(93,3)("ICAPAccessCheck::do_callback\n"); - callback(match, callback_data); - match = NULL; + ICAPClass *theClass = TheICAPConfig.findClass(matchedClass); + + if (theClass == NULL) { + callback(NULL, callback_data); + return; + } + + matchedClass.clean(); + + Vector::iterator i; + + for (i = theClass->services.begin(); i != theClass->services.end(); ++i) { + ICAPServiceRep *theService = i->getRaw(); + + if (method != theService->method) + continue; + + if (point != theService->point) + continue; + + callback(*i, callback_data); + + return; + } + + callback(NULL, callback_data); } @@ -214,17 +276,10 @@ void ICAPConfig::parseICAPClass() { - List **Tail; - ICAPClass *C = new ICAPClass(); if (C->prepare()) { - for (Tail = &classes; *Tail; Tail = &((*Tail)->next)) - - ; - List * q = new List(*C); - - *(Tail) = q; + classes.push_back(C); } else { delete C; } @@ -234,46 +289,67 @@ void ICAPConfig::freeICAPClass() { - delete classes; + classes.clean(); }; void ICAPConfig::dumpICAPClass(StoreEntry *entry, const char *name) { - List *data = classes; + Vector::iterator i = classes.begin(); - while (data != NULL) { - storeAppendPrintf(entry, "%s %s\n", name, data->element.key); - data = data->next; + while (i != classes.end()) { + storeAppendPrintf(entry, "%s %s\n", name, (*i)->key.buf()); + ++i; } }; -void -ICAPConfig::parseICAPAccess() +#if 0 +int +ICAPAccess::parseLine() { - List **Tail; + int found = 0; - ICAPAccess *A = new ICAPAccess(); + ConfigParser::ParseString(&key); - if (A->prepare()) { - for (Tail = &accesses; *Tail; Tail = &((*Tail)->next)) + Vector *data = TheICAPConfig.classes; - ; - List * q = new List(*A); + while (data != NULL) { + if (!strcmp(data->element.key, key)) { + aclass =& data->element; + found = 1; + break; + } - *(Tail) = q; + data = data->next; + } - } else { - delete A; + if (found) { + aclParseAccessLine(&(this->access)); } - return; + return found; +}; + +#endif + +void +ICAPConfig::parseICAPAccess() +{ + String aKey; + ConfigParser::ParseString(&aKey); + ICAPClass *theClass = TheICAPConfig.findClass(aKey); + + if (theClass == NULL) + fatalf("Did not find ICAP class '%s' referenced on line %d\n", + aKey.buf(), config_lineno); + + aclParseAccessLine(&theClass->accessList); }; void ICAPConfig::freeICAPAccess() { - delete accesses; + (void) 0; }; void @@ -281,29 +357,24 @@ { LOCAL_ARRAY(char, nom, 64); - if (!accesses) { - storeAppendPrintf(entry, "%s 0\n", name); - return; - } + Vector::iterator i = classes.begin(); - List *data = accesses; - - while (data != NULL) { - snprintf(nom, 64, "%s %s", name, data->element.key); - dump_acl_access(entry, nom, data->element.access); - data = data->next; + while (i != classes.end()) { + snprintf(nom, 64, "%s %s", name, (*i)->key.buf()); + dump_acl_access(entry, nom, (*i)->accessList); + ++i; } }; ICAPConfig::~ICAPConfig() { - delete classes; // invalidate each service so that it can be deleted when refcount=0 - typedef Vector::iterator VI; + Vector::iterator si; + + for (si = services.begin(); si != services.end(); ++si) + (*si)->invalidate(); - for (VI i = services.begin(); i != services.end(); ++i) - (*i)->invalidate(); + classes.clean(); - delete accesses; }; Index: squid3/src/ICAPConfig.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPConfig.h,v retrieving revision 1.1.2.5 retrieving revision 1.1.2.6 diff -u -r1.1.2.5 -r1.1.2.6 --- squid3/src/ICAPConfig.h 17 Oct 2005 22:39:13 -0000 1.1.2.5 +++ squid3/src/ICAPConfig.h 3 Nov 2005 21:36:45 -0000 1.1.2.6 @@ -1,6 +1,6 @@ /* - * $Id: ICAPConfig.h,v 1.1.2.5 2005/10/17 22:39:13 rousskov Exp $ + * $Id: ICAPConfig.h,v 1.1.2.6 2005/11/03 21:36:45 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,7 +36,6 @@ #ifndef SQUID_ICAPCONFIG_H #define SQUID_ICAPCONFIG_H -#include "List.h" #include "ICAPServiceRep.h" class acl_access; @@ -47,17 +46,19 @@ { public: - char *key; - wordlist *service_names; + String key; + acl_access *accessList; Vector services; - ICAPClass() : key(NULL), service_names(NULL) {}; + ICAPClass() : key(NULL) {}; int prepare(); }; +#if 0 + class ICAPAccess { @@ -77,6 +78,8 @@ }; +#endif + class ICAPAccessCheck { @@ -92,13 +95,15 @@ HttpReply *rep; ICAPAccessCheckCallback *callback; void *callback_data; - - ICAPServiceRep::Pointer match; + ACLChecklist *acl_checklist; + Vector candidateClasses; + String matchedClass; void do_callback(); public: void check(); - static void ICAPAccessCheckCallbackWrapper(void*); + void checkCandidates(); + static void ICAPAccessCheckCallbackWrapper(int, void*); private: CBDATA_CLASS2(ICAPAccessCheck); @@ -118,10 +123,13 @@ char *auth_scheme; Vector services; - List *classes; + Vector classes; +#if 0 + List *accesses; +#endif - ICAPConfig() : classes(NULL), accesses(NULL) {}; + ICAPConfig() {}; ~ICAPConfig(); @@ -129,6 +137,7 @@ void freeICAPService(void); void dumpICAPService(StoreEntry *, const char *); ICAPServiceRep::Pointer findService(const String&); + ICAPClass * ICAPConfig::findClass(const String& key); void parseICAPClass(void); void freeICAPClass(void);