]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
adaptation_service ACL
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Tue, 12 Nov 2013 14:48:50 +0000 (16:48 +0200)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Tue, 12 Nov 2013 14:48:50 +0000 (16:48 +0200)
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

13 files changed:
src/AclRegs.cc
src/acl/AdaptationService.cc [new file with mode: 0644]
src/acl/AdaptationService.h [new file with mode: 0644]
src/acl/AdaptationServiceData.cc [new file with mode: 0644]
src/acl/AdaptationServiceData.h [new file with mode: 0644]
src/acl/Makefile.am
src/acl/StringData.h
src/adaptation/Config.cc
src/adaptation/Config.h
src/adaptation/History.cc
src/adaptation/History.h
src/adaptation/Iterator.cc
src/cf.data.pre

index e44bdc6cd0c241916e3a610f017365e552de5e3c..548450440f9634f3f082465d3fe5ebd1a71359d0 100644 (file)
@@ -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<HttpRequest *> ACLNote::RegistryEntry_(new ACLNoteData, ACLNoteStrategy::Instance(), "note");
+
+#if USE_ADAPTATION
+ACL::Prototype ACLAdaptationService::RegistryProtoype(&ACLAdaptationService::RegistryEntry_, "adaptation_service");
+ACLStrategised<const char *> 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 (file)
index 0000000..590be9f
--- /dev/null
@@ -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<MatchType> * &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 (file)
index 0000000..630c605
--- /dev/null
@@ -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<const char *>
+{
+
+public:
+    virtual int match (ACLData<MatchType> * &, 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<const char *> RegistryEntry_;
+};
+
+#endif /* SQUID_ACLADAPTATIONSERVICE_H */
diff --git a/src/acl/AdaptationServiceData.cc b/src/acl/AdaptationServiceData.cc
new file mode 100644 (file)
index 0000000..90b32ed
--- /dev/null
@@ -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<char const *> *
+ACLAdaptationServiceData::clone() const
+{
+    return new ACLAdaptationServiceData(*this);
+}
+
diff --git a/src/acl/AdaptationServiceData.h b/src/acl/AdaptationServiceData.h
new file mode 100644 (file)
index 0000000..266e59d
--- /dev/null
@@ -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<char const *> *clone() const;
+};
+
+#endif /* SQUID_ADAPTATIONSERVICEDATA_H */
index d67059758777a87e18fb7fbd64874cd7db2be936..03bb6cb7b5631438310d8795567953a3cac8183b 100644 (file)
@@ -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)
 
 
index 4a8bab582cad940a12306a269fec528c023c3a3e..6da50f37ab5979fb6a4079555002c8b872d38773 100644 (file)
@@ -49,7 +49,7 @@ public:
     virtual ~ACLStringData();
     bool match(char const *);
     wordlist *dump();
-    void parse();
+    virtual void parse();
     bool empty() const;
     virtual ACLData<char const *> *clone() const;
     /// Insert a string data value
index d84eabddee3ded55b8e7ffae8be53a41fbd645db..18e6cbef08b2384b1713bd74fc6242abb0b47e3b 100644 (file)
@@ -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)
 {
index 15d1e5badeb511890aef59951fea059f596f3cc5..5da85bebb79b050be52152b763ed8f724cbc38d9 100644 (file)
@@ -49,6 +49,8 @@ public:
 
     static Notes metaHeaders; ///< The list of configured meta headers
 
+    static bool needHistory; ///< HttpRequest adaptation history should recorded
+
     typedef Vector<ServiceConfigPointer> 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
index 00877aefab547fa6be574095cd04b23d0ed8f708..26fb220ee2b75ab9e776013b6e8bd218e4f2d77c 100644 (file)
@@ -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)
 {
index 1ef64e4cdf0d964a096fa5807664837489052169..b502838b89d62024f2ac73eaee3fdeb9afca1740 100644 (file)
@@ -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<SBuf> AdaptationServices;
+    AdaptationServices theAdaptationServices; ///< The service groups used
+
     /// sets future services for the Adaptation::AccessCheck to notice
     void setFutureServices(const DynamicGroupCfg &services);
 
index 3b60e82b15158b3c162149a09fdb0645bcbd05bd..2d87460241ab1f66bd9ac311a2b30ebf5a81a10d 100644 (file)
@@ -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<ServiceSet *>(theGroup.getRaw()) || dynamic_cast<ServiceChain *>(theGroup.getRaw()))) {
+        HttpRequest *request = dynamic_cast<HttpRequest*>(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));
index 5b4b4ac9165c04c4144c0c7fc2225ca57c666060..5ab5ba86f106c4463b204144d0b3bc50cb9482d3 100644 (file)
@@ -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]