From: Christos Tsantilas Date: Tue, 12 Nov 2013 14:48:50 +0000 (+0200) Subject: adaptation_service ACL X-Git-Tag: SQUID_3_5_0_1~520 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c302ddb55b4dd6116b160288fd2493a7021d3ba8;p=thirdparty%2Fsquid.git adaptation_service ACL This patch adds the new ACL adaptation_service, to match the name of: - an adaptation service or group that had been applied to the master transaction in the past - an adaptation service or group that is being applied to the master transaction now An adaptation group is formed by adaptation_service_chain or adaptation_service_set directives. Both REQMOD and RESPMOD services, successful or failed service applications matches this acl. This is a Measurement Factory project --- diff --git a/src/AclRegs.cc b/src/AclRegs.cc index e44bdc6cd0..548450440f 100644 --- a/src/AclRegs.cc +++ b/src/AclRegs.cc @@ -5,6 +5,10 @@ does not get linked in, because nobody is using these classes by name. */ +#if USE_ADAPTATION +#include "acl/AdaptationService.h" +#include "acl/AdaptationServiceData.h" +#endif #include "acl/AllOf.h" #include "acl/AnyOf.h" #if USE_SQUID_EUI @@ -193,3 +197,8 @@ Acl::AllOf Acl::AllOf::RegistryEntry_; ACL::Prototype ACLNote::RegistryProtoype(&ACLNote::RegistryEntry_, "note"); ACLStrategised ACLNote::RegistryEntry_(new ACLNoteData, ACLNoteStrategy::Instance(), "note"); + +#if USE_ADAPTATION +ACL::Prototype ACLAdaptationService::RegistryProtoype(&ACLAdaptationService::RegistryEntry_, "adaptation_service"); +ACLStrategised ACLAdaptationService::RegistryEntry_(new ACLAdaptationServiceData, ACLAdaptationServiceStrategy::Instance(), "adaptation_service"); +#endif diff --git a/src/acl/AdaptationService.cc b/src/acl/AdaptationService.cc new file mode 100644 index 0000000000..590be9f8b1 --- /dev/null +++ b/src/acl/AdaptationService.cc @@ -0,0 +1,34 @@ +#include "squid.h" +#include "acl/Checklist.h" +#include "acl/IntRange.h" +#include "acl/AdaptationService.h" +#include "adaptation/Config.h" +#include "adaptation/History.h" +#include "HttpRequest.h" + +int +ACLAdaptationServiceStrategy::match (ACLData * &data, ACLFilledChecklist *checklist, ACLFlags &) +{ + HttpRequest::Pointer request = checklist->request; + if (request == NULL) + return 0; + Adaptation::History::Pointer ah = request->adaptHistory(); + if (ah == NULL) + return 0; + + Adaptation::History::AdaptationServices::iterator it; + for (it = ah->theAdaptationServices.begin(); it != ah->theAdaptationServices.end(); ++it) { + if (data->match(it->c_str())) + return 1; + } + + return 0; +} + +ACLAdaptationServiceStrategy * +ACLAdaptationServiceStrategy::Instance() +{ + return &Instance_; +} + +ACLAdaptationServiceStrategy ACLAdaptationServiceStrategy::Instance_; diff --git a/src/acl/AdaptationService.h b/src/acl/AdaptationService.h new file mode 100644 index 0000000000..630c605f3a --- /dev/null +++ b/src/acl/AdaptationService.h @@ -0,0 +1,35 @@ +#ifndef SQUID_ACLADAPTATIONSERVICE_H +#define SQUID_ACLADAPTATIONSERVICE_H + +#include "acl/Strategised.h" +#include "acl/Strategy.h" + +/// \ingroup ACLAPI +class ACLAdaptationServiceStrategy : public ACLStrategy +{ + +public: + virtual int match (ACLData * &, ACLFilledChecklist *, ACLFlags &); + static ACLAdaptationServiceStrategy *Instance(); + /** + * Not implemented to prevent copies of the instance. + */ + ACLAdaptationServiceStrategy(ACLAdaptationServiceStrategy const &); + +private: + static ACLAdaptationServiceStrategy Instance_; + ACLAdaptationServiceStrategy() {} + + ACLAdaptationServiceStrategy &operator = (ACLAdaptationServiceStrategy const &); +}; + +/// \ingroup ACLAPI +class ACLAdaptationService +{ + +private: + static ACL::Prototype RegistryProtoype; + static ACLStrategised RegistryEntry_; +}; + +#endif /* SQUID_ACLADAPTATIONSERVICE_H */ diff --git a/src/acl/AdaptationServiceData.cc b/src/acl/AdaptationServiceData.cc new file mode 100644 index 0000000000..90b32ed867 --- /dev/null +++ b/src/acl/AdaptationServiceData.cc @@ -0,0 +1,39 @@ +#include "squid.h" +#include "acl/AdaptationServiceData.h" +#include "acl/Checklist.h" +#include "adaptation/Config.h" +#include "adaptation/ecap/Config.h" +#include "adaptation/icap/Config.h" +#include "adaptation/Service.h" +#include "adaptation/ServiceGroups.h" +#include "cache_cf.h" +#include "ConfigParser.h" +#include "Debug.h" +#include "wordlist.h" + +void +ACLAdaptationServiceData::parse() +{ + Adaptation::Config::needHistory = true; + while (char *t = ConfigParser::strtokFile()) { + if ( +#if USE_ECAP + Adaptation::Ecap::TheConfig.findServiceConfig(t) == NULL && +#endif +#if ICAP_CLIENT + Adaptation::Icap::TheConfig.findServiceConfig(t) == NULL && +#endif + Adaptation::FindGroup(t) == NULL) { + debugs(28, DBG_CRITICAL, "FATAL: Adaptation service/group " << t << " in adaptation_service acl is not defined"); + self_destruct(); + } + insert(t); + } +} + +ACLData * +ACLAdaptationServiceData::clone() const +{ + return new ACLAdaptationServiceData(*this); +} + diff --git a/src/acl/AdaptationServiceData.h b/src/acl/AdaptationServiceData.h new file mode 100644 index 0000000000..266e59d64a --- /dev/null +++ b/src/acl/AdaptationServiceData.h @@ -0,0 +1,21 @@ + +#ifndef SQUID_ADAPTATIONSERVICEDATA_H +#define SQUID_ADAPTATIONSERVICEDATA_H + +#include "acl/Acl.h" +#include "acl/Data.h" +#include "acl/StringData.h" + +/// \ingroup ACLAPI +class ACLAdaptationServiceData : public ACLStringData +{ +public: + ACLAdaptationServiceData() : ACLStringData() {} + ACLAdaptationServiceData(ACLAdaptationServiceData const &old) : ACLStringData(old) {}; + // Not implemented + ACLAdaptationServiceData &operator= (ACLAdaptationServiceData const &); + virtual void parse(); + virtual ACLData *clone() const; +}; + +#endif /* SQUID_ADAPTATIONSERVICEDATA_H */ diff --git a/src/acl/Makefile.am b/src/acl/Makefile.am index d670597587..03bb6cb7b5 100644 --- a/src/acl/Makefile.am +++ b/src/acl/Makefile.am @@ -148,6 +148,14 @@ if ENABLE_SSL libacls_la_SOURCES += $(SSL_ACLS) endif +if USE_ADAPTATION +libacls_la_SOURCES += AdaptationService.h \ + AdaptationService.cc \ + AdaptationServiceData.h \ + AdaptationServiceData.cc +endif + + EXTRA_libacls_la_SOURCES += $(SSL_ACLS) diff --git a/src/acl/StringData.h b/src/acl/StringData.h index 4a8bab582c..6da50f37ab 100644 --- a/src/acl/StringData.h +++ b/src/acl/StringData.h @@ -49,7 +49,7 @@ public: virtual ~ACLStringData(); bool match(char const *); wordlist *dump(); - void parse(); + virtual void parse(); bool empty() const; virtual ACLData *clone() const; /// Insert a string data value diff --git a/src/adaptation/Config.cc b/src/adaptation/Config.cc index d84eabddee..18e6cbef08 100644 --- a/src/adaptation/Config.cc +++ b/src/adaptation/Config.cc @@ -67,6 +67,7 @@ const char *metasBlacklist[] = { NULL }; Notes Adaptation::Config::metaHeaders("ICAP header", metasBlacklist); +bool Adaptation::Config::needHistory = false; Adaptation::ServiceConfig* Adaptation::Config::newServiceConfig() const @@ -101,6 +102,18 @@ Adaptation::Config::removeService(const String& service) } } +Adaptation::ServiceConfigPointer +Adaptation::Config::findServiceConfig(const String &service) +{ + typedef ServiceConfigs::const_iterator SCI; + const ServiceConfigs& configs = serviceConfigs; + for (SCI cfg = configs.begin(); cfg != configs.end(); ++cfg) { + if ((*cfg)->key == service) + return *cfg; + } + return NULL; +} + void Adaptation::Config::removeRule(const String& id) { diff --git a/src/adaptation/Config.h b/src/adaptation/Config.h index 15d1e5bade..5da85bebb7 100644 --- a/src/adaptation/Config.h +++ b/src/adaptation/Config.h @@ -49,6 +49,8 @@ public: static Notes metaHeaders; ///< The list of configured meta headers + static bool needHistory; ///< HttpRequest adaptation history should recorded + typedef Vector ServiceConfigs; ServiceConfigs serviceConfigs; @@ -58,7 +60,7 @@ public: void parseService(void); void freeService(void); void dumpService(StoreEntry *, const char *) const; - ServicePointer findService(const String&); + ServiceConfigPointer findServiceConfig(const String&); /** * Creates and starts the adaptation services. In the case the adaptation diff --git a/src/adaptation/History.cc b/src/adaptation/History.cc index 00877aefab..26fb220ee2 100644 --- a/src/adaptation/History.cc +++ b/src/adaptation/History.cc @@ -148,6 +148,12 @@ void Adaptation::History::recordMeta(const HttpHeader *lm) allMeta.compact(); } +void +Adaptation::History::recordAdaptationService(SBuf &srvId) +{ + theAdaptationServices.push_back(srvId); +} + void Adaptation::History::setFutureServices(const DynamicGroupCfg &services) { diff --git a/src/adaptation/History.h b/src/adaptation/History.h index 1ef64e4cdf..b502838b89 100644 --- a/src/adaptation/History.h +++ b/src/adaptation/History.h @@ -6,6 +6,7 @@ #include "base/Vector.h" #include "HttpHeader.h" #include "Notes.h" +#include "SBuf.h" #include "SquidString.h" namespace Adaptation @@ -46,6 +47,7 @@ public: /// store the last meta header fields received from the adaptation service void recordMeta(const HttpHeader *lm); + void recordAdaptationService(SBuf &srvId); public: /// Last received meta header (REQMOD or RESPMOD, whichever comes last). HttpHeader lastMeta; @@ -55,6 +57,9 @@ public: /// AccessLogEntry::notes when ALE becomes available NotePairs::Pointer metaHeaders; + typedef Vector AdaptationServices; + AdaptationServices theAdaptationServices; ///< The service groups used + /// sets future services for the Adaptation::AccessCheck to notice void setFutureServices(const DynamicGroupCfg &services); diff --git a/src/adaptation/Iterator.cc b/src/adaptation/Iterator.cc index 3b60e82b15..2d87460241 100644 --- a/src/adaptation/Iterator.cc +++ b/src/adaptation/Iterator.cc @@ -45,6 +45,19 @@ void Adaptation::Iterator::start() Adaptation::Initiate::start(); thePlan = ServicePlan(theGroup, filter()); + + // Add adaptation group name once and now, before + // dynamic groups change it at step() time. + if (Adaptation::Config::needHistory && !thePlan.exhausted() && (dynamic_cast(theGroup.getRaw()) || dynamic_cast(theGroup.getRaw()))) { + HttpRequest *request = dynamic_cast(theMsg); + if (!request) + request = theCause; + Must(request); + Adaptation::History::Pointer ah = request->adaptHistory(true); + SBuf gid(theGroup->id); + ah->recordAdaptationService(gid); + } + step(); } @@ -79,6 +92,12 @@ void Adaptation::Iterator::step() Must(service != NULL); debugs(93,5, HERE << "using adaptation service: " << service->cfg().key); + if (Adaptation::Config::needHistory) { + Adaptation::History::Pointer ah = request->adaptHistory(true); + SBuf uid(thePlan.current()->cfg().key); + ah->recordAdaptationService(uid); + } + theLauncher = initiateAdaptation( service->makeXactLauncher(theMsg, theCause)); Must(initiated(theLauncher)); diff --git a/src/cf.data.pre b/src/cf.data.pre index 5b4b4ac916..5ab5ba86f1 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -1073,6 +1073,15 @@ DOC_START # Annotation sources include note and adaptation_meta directives # as well as helper and eCAP responses. + acl aclname adaptation_service service ... + # Matches the name of any icap_service, ecap_service, + # adaptation_service_set, or adaptation_service_chain that Squid + # has used (or attempted to use) for the master transaction. + # This ACL must be defined after the corresponding adaptation + # service is named in squid.conf. This ACL is usable with + # adaptation_meta because it starts matching immediately after + # the service has been selected for adaptation. + IF USE_SSL acl aclname ssl_error errorname # match against SSL certificate validation error [fast]