2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
10 #include "acl/FilledChecklist.h"
11 #include "acl/Gadgets.h"
12 #include "adaptation/AccessRule.h"
13 #include "adaptation/Config.h"
14 #include "adaptation/History.h"
15 #include "adaptation/Service.h"
16 #include "adaptation/ServiceGroups.h"
17 #include "ConfigParser.h"
19 #include "HttpReply.h"
20 #include "HttpRequest.h"
25 bool Adaptation::Config::Enabled
= false;
26 char *Adaptation::Config::masterx_shared_name
= NULL
;
27 int Adaptation::Config::service_iteration_limit
= 16;
28 int Adaptation::Config::send_client_ip
= false;
29 int Adaptation::Config::send_username
= false;
30 int Adaptation::Config::use_indirect_client
= true;
31 const char *metasBlacklist
[] = {
48 Notes
Adaptation::Config::metaHeaders("ICAP header", metasBlacklist
);
49 bool Adaptation::Config::needHistory
= false;
51 Adaptation::ServiceConfig
*
52 Adaptation::Config::newServiceConfig() const
54 return new ServiceConfig();
58 Adaptation::Config::removeService(const String
& service
)
61 const Groups
& groups
= AllGroups();
62 for (unsigned int i
= 0; i
< groups
.size(); ) {
63 const ServiceGroupPointer group
= groups
[i
];
64 const ServiceGroup::Store
& services
= group
->services
;
65 typedef ServiceGroup::Store::const_iterator SGSI
;
66 for (SGSI it
= services
.begin(); it
!= services
.end(); ++it
) {
68 group
->removedServices
.push_back(service
);
69 ServiceGroup::Store::iterator newend
;
70 newend
= std::remove(group
->services
.begin(), group
->services
.end(), service
);
71 group
->services
.resize(newend
-group
->services
.begin());
72 debugs(93, 5, "adaptation service " << service
<<
73 " removed from group " << group
->id
);
77 if (services
.empty()) {
78 removeRule(group
->id
);
79 Groups::iterator newend
;
80 newend
= std::remove(AllGroups().begin(), AllGroups().end(), group
);
81 AllGroups().resize(newend
-AllGroups().begin());
88 Adaptation::ServiceConfigPointer
89 Adaptation::Config::findServiceConfig(const String
&service
)
91 typedef ServiceConfigs::const_iterator SCI
;
92 const ServiceConfigs
& configs
= serviceConfigs
;
93 for (SCI cfg
= configs
.begin(); cfg
!= configs
.end(); ++cfg
) {
94 if ((*cfg
)->key
== service
)
101 Adaptation::Config::removeRule(const String
& id
)
103 typedef AccessRules::const_iterator ARI
;
104 const AccessRules
& rules
= AllRules();
105 for (ARI it
= rules
.begin(); it
!= rules
.end(); ++it
) {
106 AccessRule
* rule
= *it
;
107 if (rule
->groupId
== id
) {
108 debugs(93, 5, "removing access rules for:" << id
);
109 AccessRules::iterator newend
;
110 newend
= std::remove(AllRules().begin(), AllRules().end(), rule
);
111 AllRules().resize(newend
-AllRules().begin());
119 Adaptation::Config::clear()
121 debugs(93, 3, HERE
<< "rules: " << AllRules().size() << ", groups: " <<
122 AllGroups().size() << ", services: " << serviceConfigs
.size());
123 typedef ServiceConfigs::const_iterator SCI
;
124 const ServiceConfigs
& configs
= serviceConfigs
;
125 for (SCI cfg
= configs
.begin(); cfg
!= configs
.end(); ++cfg
)
126 removeService((*cfg
)->key
);
127 serviceConfigs
.clear();
128 debugs(93, 3, HERE
<< "rules: " << AllRules().size() << ", groups: " <<
129 AllGroups().size() << ", services: " << serviceConfigs
.size());
133 Adaptation::Config::parseService()
135 ServiceConfigPointer cfg
= newServiceConfig();
137 fatalf("%s:%d: malformed adaptation service configuration",
138 cfg_filename
, config_lineno
);
140 serviceConfigs
.push_back(cfg
);
144 Adaptation::Config::freeService()
151 serviceConfigs
.clear();
155 Adaptation::Config::dumpService(StoreEntry
*entry
, const char *name
) const
157 typedef Services::iterator SCI
;
158 for (SCI i
= AllServices().begin(); i
!= AllServices().end(); ++i
) {
159 const ServiceConfig
&cfg
= (*i
)->cfg();
160 bool isEcap
= cfg
.protocol
.caseCmp("ecap") == 0;
161 bool isIcap
= !isEcap
;
162 const char *optConnectionEncryption
= "";
163 // Print connections_encrypted option if no default value is used
164 if (cfg
.secure
.encryptTransport
&& !cfg
.connectionEncryption
)
165 optConnectionEncryption
= " connection-encryption=off";
166 else if (isEcap
&& !cfg
.connectionEncryption
)
167 optConnectionEncryption
= " connection-encryption=off";
168 else if (isIcap
&& !cfg
.secure
.encryptTransport
&& cfg
.connectionEncryption
)
169 optConnectionEncryption
= " connection-encryption=on";
171 storeAppendPrintf(entry
, "%s " SQUIDSTRINGPH
" %s_%s %d " SQUIDSTRINGPH
"%s\n",
173 SQUIDSTRINGPRINT(cfg
.key
),
174 cfg
.methodStr(), cfg
.vectPointStr(), cfg
.bypass
,
175 SQUIDSTRINGPRINT(cfg
.uri
),
177 optConnectionEncryption
);
182 Adaptation::Config::finalize()
189 // create service reps from service configs
192 typedef ServiceConfigs::const_iterator VISCI
;
193 const ServiceConfigs
&configs
= serviceConfigs
;
194 for (VISCI i
= configs
.begin(); i
!= configs
.end(); ++i
) {
195 const ServiceConfigPointer cfg
= *i
;
196 if (FindService(cfg
->key
) != NULL
) {
197 debugs(93, DBG_CRITICAL
, "ERROR: Duplicate adaptation service name: " <<
199 continue; // TODO: make fatal
201 ServicePointer s
= createService(cfg
);
203 AllServices().push_back(s
);
208 debugs(93,3, HERE
<< "Created " << created
<< " adaptation services");
210 // services remember their configs; we do not have to
211 serviceConfigs
.clear();
216 template <class Collection
>
218 FinalizeEach(Collection
&collection
, const char *label
)
220 typedef typename
Collection::iterator CI
;
221 for (CI i
= collection
.begin(); i
!= collection
.end(); ++i
)
224 debugs(93,2, HERE
<< "Initialized " << collection
.size() << ' ' << label
);
228 Adaptation::Config::Finalize(bool enabled
)
231 debugs(93, DBG_IMPORTANT
, "Adaptation support is " << (Enabled
? "on" : "off."));
233 FinalizeEach(AllServices(), "message adaptation services");
234 FinalizeEach(AllGroups(), "message adaptation service groups");
235 FinalizeEach(AllRules(), "message adaptation access rules");
239 Adaptation::Config::ParseServiceSet()
241 Adaptation::Config::ParseServiceGroup(new ServiceSet
);
245 Adaptation::Config::ParseServiceChain()
247 Adaptation::Config::ParseServiceGroup(new ServiceChain
);
251 Adaptation::Config::ParseServiceGroup(ServiceGroupPointer g
)
255 AllGroups().push_back(g
);
259 Adaptation::Config::FreeServiceGroups()
261 while (!AllGroups().empty()) {
262 // groups are refcounted so we do not explicitly delete them
263 AllGroups().pop_back();
268 Adaptation::Config::DumpServiceGroups(StoreEntry
*entry
, const char *name
)
270 typedef Groups::iterator GI
;
271 for (GI i
= AllGroups().begin(); i
!= AllGroups().end(); ++i
)
272 storeAppendPrintf(entry
, "%s " SQUIDSTRINGPH
"\n", name
, SQUIDSTRINGPRINT((*i
)->id
));
276 Adaptation::Config::ParseAccess(ConfigParser
&parser
)
278 String groupId
= ConfigParser::NextToken();
280 if (!(r
=FindRuleByGroupId(groupId
))) {
281 r
= new AccessRule(groupId
);
282 AllRules().push_back(r
);
288 Adaptation::Config::FreeAccess()
290 while (!AllRules().empty()) {
291 delete AllRules().back();
292 AllRules().pop_back();
297 Adaptation::Config::DumpAccess(StoreEntry
*entry
, const char *name
)
299 LOCAL_ARRAY(char, nom
, 64);
301 typedef AccessRules::iterator CI
;
302 for (CI i
= AllRules().begin(); i
!= AllRules().end(); ++i
) {
303 snprintf(nom
, 64, "%s " SQUIDSTRINGPH
, name
, SQUIDSTRINGPRINT((*i
)->groupId
));
304 dump_acl_access(entry
, nom
, (*i
)->acl
);
308 Adaptation::Config::Config() :
309 onoff(0), service_failure_limit(0), oldest_service_failure(0),
310 service_revival_delay(0)
313 // XXX: this is called for ICAP and eCAP configs, but deals mostly
314 // with global arrays shared by those individual configs
315 Adaptation::Config::~Config()