]> git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/Config.cc
Boilerplate: update copyright blurbs on src/
[thirdparty/squid.git] / src / adaptation / Config.cc
1 /*
2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
3 *
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.
7 */
8
9 #include "squid.h"
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 "globals.h"
19 #include "HttpReply.h"
20 #include "HttpRequest.h"
21 #include "Store.h"
22
23 #include <algorithm>
24
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[] = {
32 "Methods",
33 "Service",
34 "ISTag",
35 "Encapsulated",
36 "Opt-body-type",
37 "Max-Connections",
38 "Options-TTL",
39 "Date",
40 "Service-ID",
41 "Allow",
42 "Preview",
43 "Transfer-Preview",
44 "Transfer-Ignore",
45 "Transfer-Complete",
46 NULL
47 };
48 Notes Adaptation::Config::metaHeaders("ICAP header", metasBlacklist, true);
49 bool Adaptation::Config::needHistory = false;
50
51 Adaptation::ServiceConfig*
52 Adaptation::Config::newServiceConfig() const
53 {
54 return new ServiceConfig();
55 }
56
57 void
58 Adaptation::Config::removeService(const String& service)
59 {
60 removeRule(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) {
67 if (*it == service) {
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);
74 break;
75 }
76 }
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());
82 } else {
83 ++i;
84 }
85 }
86 }
87
88 Adaptation::ServiceConfigPointer
89 Adaptation::Config::findServiceConfig(const String &service)
90 {
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)
95 return *cfg;
96 }
97 return NULL;
98 }
99
100 void
101 Adaptation::Config::removeRule(const String& id)
102 {
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());
112 delete (rule);
113 break;
114 }
115 }
116 }
117
118 void
119 Adaptation::Config::clear()
120 {
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());
130 }
131
132 void
133 Adaptation::Config::parseService()
134 {
135 ServiceConfigPointer cfg = newServiceConfig();
136 if (!cfg->parse()) {
137 fatalf("%s:%d: malformed adaptation service configuration",
138 cfg_filename, config_lineno);
139 }
140 serviceConfigs.push_back(cfg);
141 }
142
143 void
144 Adaptation::Config::freeService()
145 {
146 FreeAccess();
147 FreeServiceGroups();
148
149 DetachServices();
150
151 serviceConfigs.clear();
152 }
153
154 void
155 Adaptation::Config::dumpService(StoreEntry *entry, const char *name) const
156 {
157 typedef Services::iterator SCI;
158 for (SCI i = AllServices().begin(); i != AllServices().end(); ++i) {
159 const ServiceConfig &cfg = (*i)->cfg();
160 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "_%s %s %d " SQUIDSTRINGPH "\n",
161 name,
162 SQUIDSTRINGPRINT(cfg.key),
163 cfg.methodStr(), cfg.vectPointStr(), cfg.bypass,
164 SQUIDSTRINGPRINT(cfg.uri));
165 }
166 }
167
168 bool
169 Adaptation::Config::finalize()
170 {
171 if (!onoff) {
172 clear();
173 return false;
174 }
175
176 // create service reps from service configs
177 int created = 0;
178
179 typedef ServiceConfigs::const_iterator VISCI;
180 const ServiceConfigs &configs = serviceConfigs;
181 for (VISCI i = configs.begin(); i != configs.end(); ++i) {
182 const ServiceConfigPointer cfg = *i;
183 if (FindService(cfg->key) != NULL) {
184 debugs(93, DBG_CRITICAL, "ERROR: Duplicate adaptation service name: " <<
185 cfg->key);
186 continue; // TODO: make fatal
187 }
188 ServicePointer s = createService(cfg);
189 if (s != NULL) {
190 AllServices().push_back(s);
191 ++created;
192 }
193 }
194
195 debugs(93,3, HERE << "Created " << created << " adaptation services");
196
197 // services remember their configs; we do not have to
198 serviceConfigs.clear();
199 return true;
200 }
201
202 // poor man for_each
203 template <class Collection>
204 static void
205 FinalizeEach(Collection &collection, const char *label)
206 {
207 typedef typename Collection::iterator CI;
208 for (CI i = collection.begin(); i != collection.end(); ++i)
209 (*i)->finalize();
210
211 debugs(93,2, HERE << "Initialized " << collection.size() << ' ' << label);
212 }
213
214 void
215 Adaptation::Config::Finalize(bool enabled)
216 {
217 Enabled = enabled;
218 debugs(93, DBG_IMPORTANT, "Adaptation support is " << (Enabled ? "on" : "off."));
219
220 FinalizeEach(AllServices(), "message adaptation services");
221 FinalizeEach(AllGroups(), "message adaptation service groups");
222 FinalizeEach(AllRules(), "message adaptation access rules");
223 }
224
225 void
226 Adaptation::Config::ParseServiceSet()
227 {
228 Adaptation::Config::ParseServiceGroup(new ServiceSet);
229 }
230
231 void
232 Adaptation::Config::ParseServiceChain()
233 {
234 Adaptation::Config::ParseServiceGroup(new ServiceChain);
235 }
236
237 void
238 Adaptation::Config::ParseServiceGroup(ServiceGroupPointer g)
239 {
240 assert(g != NULL);
241 g->parse();
242 AllGroups().push_back(g);
243 }
244
245 void
246 Adaptation::Config::FreeServiceGroups()
247 {
248 while (!AllGroups().empty()) {
249 // groups are refcounted so we do not explicitly delete them
250 AllGroups().pop_back();
251 }
252 }
253
254 void
255 Adaptation::Config::DumpServiceGroups(StoreEntry *entry, const char *name)
256 {
257 typedef Groups::iterator GI;
258 for (GI i = AllGroups().begin(); i != AllGroups().end(); ++i)
259 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "\n", name, SQUIDSTRINGPRINT((*i)->id));
260 }
261
262 void
263 Adaptation::Config::ParseAccess(ConfigParser &parser)
264 {
265 String groupId = ConfigParser::NextToken();
266 AccessRule *r;
267 if (!(r=FindRuleByGroupId(groupId))) {
268 r = new AccessRule(groupId);
269 AllRules().push_back(r);
270 }
271 r->parse(parser);
272 }
273
274 void
275 Adaptation::Config::FreeAccess()
276 {
277 while (!AllRules().empty()) {
278 delete AllRules().back();
279 AllRules().pop_back();
280 }
281 }
282
283 void
284 Adaptation::Config::DumpAccess(StoreEntry *entry, const char *name)
285 {
286 LOCAL_ARRAY(char, nom, 64);
287
288 typedef AccessRules::iterator CI;
289 for (CI i = AllRules().begin(); i != AllRules().end(); ++i) {
290 snprintf(nom, 64, "%s " SQUIDSTRINGPH, name, SQUIDSTRINGPRINT((*i)->groupId));
291 dump_acl_access(entry, nom, (*i)->acl);
292 }
293 }
294
295 Adaptation::Config::Config() :
296 onoff(0), service_failure_limit(0), oldest_service_failure(0),
297 service_revival_delay(0)
298 {}
299
300 // XXX: this is called for ICAP and eCAP configs, but deals mostly
301 // with global arrays shared by those individual configs
302 Adaptation::Config::~Config()
303 {
304 freeService();
305 }