2 * Copyright (C) 1996-2021 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"
18 #include "DebugMessages.h"
20 #include "HttpReply.h"
21 #include "HttpRequest.h"
26 bool Adaptation::Config::Enabled
= false;
27 char *Adaptation::Config::masterx_shared_name
= NULL
;
28 int Adaptation::Config::service_iteration_limit
= 16;
29 int Adaptation::Config::send_client_ip
= false;
30 int Adaptation::Config::send_username
= false;
31 int Adaptation::Config::use_indirect_client
= true;
32 static const char *protectedFieldNamesRaw
[] = {
48 static const Notes::Keys
protectedFieldNames(std::begin(protectedFieldNamesRaw
), std::end(protectedFieldNamesRaw
));
49 Notes
Adaptation::Config::metaHeaders("ICAP header", &protectedFieldNames
);
50 bool Adaptation::Config::needHistory
= false;
52 Adaptation::ServiceConfig
*
53 Adaptation::Config::newServiceConfig() const
55 return new ServiceConfig();
59 Adaptation::Config::removeService(const String
& service
)
62 const Groups
& groups
= AllGroups();
63 for (unsigned int i
= 0; i
< groups
.size(); ) {
64 const ServiceGroupPointer group
= groups
[i
];
65 const ServiceGroup::Store
& services
= group
->services
;
66 typedef ServiceGroup::Store::const_iterator SGSI
;
67 for (SGSI it
= services
.begin(); it
!= services
.end(); ++it
) {
69 group
->removedServices
.push_back(service
);
70 ServiceGroup::Store::iterator newend
;
71 newend
= std::remove(group
->services
.begin(), group
->services
.end(), service
);
72 group
->services
.resize(newend
-group
->services
.begin());
73 debugs(93, 5, "adaptation service " << service
<<
74 " removed from group " << group
->id
);
78 if (services
.empty()) {
79 removeRule(group
->id
);
80 Groups::iterator newend
;
81 newend
= std::remove(AllGroups().begin(), AllGroups().end(), group
);
82 AllGroups().resize(newend
-AllGroups().begin());
89 Adaptation::ServiceConfigPointer
90 Adaptation::Config::findServiceConfig(const String
&service
)
92 typedef ServiceConfigs::const_iterator SCI
;
93 const ServiceConfigs
& configs
= serviceConfigs
;
94 for (SCI cfg
= configs
.begin(); cfg
!= configs
.end(); ++cfg
) {
95 if ((*cfg
)->key
== service
)
102 Adaptation::Config::removeRule(const String
& id
)
104 typedef AccessRules::const_iterator ARI
;
105 const AccessRules
& rules
= AllRules();
106 for (ARI it
= rules
.begin(); it
!= rules
.end(); ++it
) {
107 AccessRule
* rule
= *it
;
108 if (rule
->groupId
== id
) {
109 debugs(93, 5, "removing access rules for:" << id
);
110 AccessRules::iterator newend
;
111 newend
= std::remove(AllRules().begin(), AllRules().end(), rule
);
112 AllRules().resize(newend
-AllRules().begin());
120 Adaptation::Config::clear()
122 debugs(93, 3, HERE
<< "rules: " << AllRules().size() << ", groups: " <<
123 AllGroups().size() << ", services: " << serviceConfigs
.size());
124 typedef ServiceConfigs::const_iterator SCI
;
125 const ServiceConfigs
& configs
= serviceConfigs
;
126 for (SCI cfg
= configs
.begin(); cfg
!= configs
.end(); ++cfg
)
127 removeService((*cfg
)->key
);
128 serviceConfigs
.clear();
129 debugs(93, 3, HERE
<< "rules: " << AllRules().size() << ", groups: " <<
130 AllGroups().size() << ", services: " << serviceConfigs
.size());
134 Adaptation::Config::parseService()
136 ServiceConfigPointer cfg
= newServiceConfig();
138 fatalf("%s:%d: malformed adaptation service configuration",
139 cfg_filename
, config_lineno
);
141 serviceConfigs
.push_back(cfg
);
145 Adaptation::Config::freeService()
152 serviceConfigs
.clear();
156 Adaptation::Config::dumpService(StoreEntry
*entry
, const char *name
) const
158 typedef Services::iterator SCI
;
159 for (SCI i
= AllServices().begin(); i
!= AllServices().end(); ++i
) {
160 const ServiceConfig
&cfg
= (*i
)->cfg();
161 bool isEcap
= cfg
.protocol
.caseCmp("ecap") == 0;
162 bool isIcap
= !isEcap
;
163 const char *optConnectionEncryption
= "";
164 // Print connections_encrypted option if no default value is used
165 if (cfg
.secure
.encryptTransport
&& !cfg
.connectionEncryption
)
166 optConnectionEncryption
= " connection-encryption=off";
167 else if (isEcap
&& !cfg
.connectionEncryption
)
168 optConnectionEncryption
= " connection-encryption=off";
169 else if (isIcap
&& !cfg
.secure
.encryptTransport
&& cfg
.connectionEncryption
)
170 optConnectionEncryption
= " connection-encryption=on";
172 storeAppendPrintf(entry
, "%s " SQUIDSTRINGPH
" %s_%s %d " SQUIDSTRINGPH
"%s\n",
174 SQUIDSTRINGPRINT(cfg
.key
),
175 cfg
.methodStr(), cfg
.vectPointStr(), cfg
.bypass
,
176 SQUIDSTRINGPRINT(cfg
.uri
),
178 optConnectionEncryption
);
183 Adaptation::Config::finalize()
190 // create service reps from service configs
193 typedef ServiceConfigs::const_iterator VISCI
;
194 const ServiceConfigs
&configs
= serviceConfigs
;
195 for (VISCI i
= configs
.begin(); i
!= configs
.end(); ++i
) {
196 const ServiceConfigPointer cfg
= *i
;
197 if (FindService(cfg
->key
) != NULL
) {
198 debugs(93, DBG_CRITICAL
, "ERROR: Duplicate adaptation service name: " <<
200 continue; // TODO: make fatal
202 ServicePointer s
= createService(cfg
);
204 AllServices().push_back(s
);
209 debugs(93,3, HERE
<< "Created " << created
<< " adaptation services");
211 // services remember their configs; we do not have to
212 serviceConfigs
.clear();
217 template <class Collection
>
219 FinalizeEach(Collection
&collection
, const char *label
)
221 typedef typename
Collection::iterator CI
;
222 for (CI i
= collection
.begin(); i
!= collection
.end(); ++i
)
225 debugs(93,2, HERE
<< "Initialized " << collection
.size() << ' ' << label
);
229 Adaptation::Config::Finalize(bool enabled
)
232 debugs(93, Important(11), "Adaptation support is " << (Enabled
? "on" : "off."));
234 FinalizeEach(AllServices(), "message adaptation services");
235 FinalizeEach(AllGroups(), "message adaptation service groups");
236 FinalizeEach(AllRules(), "message adaptation access rules");
240 Adaptation::Config::ParseServiceSet()
242 Adaptation::Config::ParseServiceGroup(new ServiceSet
);
246 Adaptation::Config::ParseServiceChain()
248 Adaptation::Config::ParseServiceGroup(new ServiceChain
);
252 Adaptation::Config::ParseServiceGroup(ServiceGroupPointer g
)
256 AllGroups().push_back(g
);
260 Adaptation::Config::FreeServiceGroups()
262 while (!AllGroups().empty()) {
263 // groups are refcounted so we do not explicitly delete them
264 AllGroups().pop_back();
269 Adaptation::Config::DumpServiceGroups(StoreEntry
*entry
, const char *name
)
271 typedef Groups::iterator GI
;
272 for (GI i
= AllGroups().begin(); i
!= AllGroups().end(); ++i
)
273 storeAppendPrintf(entry
, "%s " SQUIDSTRINGPH
"\n", name
, SQUIDSTRINGPRINT((*i
)->id
));
277 Adaptation::Config::ParseAccess(ConfigParser
&parser
)
279 String groupId
= ConfigParser::NextToken();
281 if (!(r
=FindRuleByGroupId(groupId
))) {
282 r
= new AccessRule(groupId
);
283 AllRules().push_back(r
);
289 Adaptation::Config::FreeAccess()
291 while (!AllRules().empty()) {
292 delete AllRules().back();
293 AllRules().pop_back();
298 Adaptation::Config::DumpAccess(StoreEntry
*entry
, const char *name
)
300 LOCAL_ARRAY(char, nom
, 64);
302 typedef AccessRules::iterator CI
;
303 for (CI i
= AllRules().begin(); i
!= AllRules().end(); ++i
) {
304 snprintf(nom
, 64, "%s " SQUIDSTRINGPH
, name
, SQUIDSTRINGPRINT((*i
)->groupId
));
305 dump_acl_access(entry
, nom
, (*i
)->acl
);
309 Adaptation::Config::Config() :
310 onoff(0), service_failure_limit(0), oldest_service_failure(0),
311 service_revival_delay(0)
314 // XXX: this is called for ICAP and eCAP configs, but deals mostly
315 // with global arrays shared by those individual configs
316 Adaptation::Config::~Config()