]> git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/Config.cc
Merged from trunk
[thirdparty/squid.git] / src / adaptation / Config.cc
1
2 /*
3 * SQUID Web Proxy Cache http://www.squid-cache.org/
4 * ----------------------------------------------------------
5 *
6 * Squid is the result of efforts by numerous individuals from
7 * the Internet community; see the CONTRIBUTORS file for full
8 * details. Many organizations have provided support for Squid's
9 * development; see the SPONSORS file for full details. Squid is
10 * Copyrighted (C) 2001 by the Regents of the University of
11 * California; see the COPYRIGHT file for full details. Squid
12 * incorporates software developed and/or copyrighted by other
13 * sources; see the CREDITS file for full details.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
28 *
29 */
30
31 #include "squid.h"
32 #include "acl/FilledChecklist.h"
33 #include "acl/Gadgets.h"
34 #include "adaptation/AccessRule.h"
35 #include "adaptation/Config.h"
36 #include "adaptation/History.h"
37 #include "adaptation/Service.h"
38 #include "adaptation/ServiceGroups.h"
39 #include "base/Vector.h"
40 #include "ConfigParser.h"
41 #include "globals.h"
42 #include "HttpReply.h"
43 #include "HttpRequest.h"
44 #include "Store.h"
45
46 bool Adaptation::Config::Enabled = false;
47 char *Adaptation::Config::masterx_shared_name = NULL;
48 int Adaptation::Config::service_iteration_limit = 16;
49 int Adaptation::Config::send_client_ip = false;
50 int Adaptation::Config::send_username = false;
51 int Adaptation::Config::use_indirect_client = true;
52 const char *metasBlacklist[] = {
53 "Methods",
54 "Service",
55 "ISTag",
56 "Encapsulated",
57 "Opt-body-type",
58 "Max-Connections",
59 "Options-TTL",
60 "Date",
61 "Service-ID",
62 "Allow",
63 "Preview",
64 "Transfer-Preview",
65 "Transfer-Ignore",
66 "Transfer-Complete",
67 NULL
68 };
69 Notes Adaptation::Config::metaHeaders("ICAP header", metasBlacklist, true);
70 bool Adaptation::Config::needHistory = false;
71
72 Adaptation::ServiceConfig*
73 Adaptation::Config::newServiceConfig() const
74 {
75 return new ServiceConfig();
76 }
77
78 void
79 Adaptation::Config::removeService(const String& service)
80 {
81 removeRule(service);
82 const Groups& groups = AllGroups();
83 for (unsigned int i = 0; i < groups.size(); ) {
84 const ServiceGroupPointer group = groups[i];
85 const ServiceGroup::Store& services = group->services;
86 typedef ServiceGroup::Store::const_iterator SGSI;
87 for (SGSI it = services.begin(); it != services.end(); ++it) {
88 if (*it == service) {
89 group->removedServices.push_back(service);
90 group->services.prune(service);
91 debugs(93, 5, HERE << "adaptation service " << service <<
92 " removed from group " << group->id);
93 break;
94 }
95 }
96 if (services.empty()) {
97 removeRule(group->id);
98 AllGroups().prune(group);
99 } else {
100 ++i;
101 }
102 }
103 }
104
105 Adaptation::ServiceConfigPointer
106 Adaptation::Config::findServiceConfig(const String &service)
107 {
108 typedef ServiceConfigs::const_iterator SCI;
109 const ServiceConfigs& configs = serviceConfigs;
110 for (SCI cfg = configs.begin(); cfg != configs.end(); ++cfg) {
111 if ((*cfg)->key == service)
112 return *cfg;
113 }
114 return NULL;
115 }
116
117 void
118 Adaptation::Config::removeRule(const String& id)
119 {
120 typedef AccessRules::const_iterator ARI;
121 const AccessRules& rules = AllRules();
122 for (ARI it = rules.begin(); it != rules.end(); ++it) {
123 AccessRule* rule = *it;
124 if (rule->groupId == id) {
125 debugs(93, 5, HERE << "removing access rules for:" << id);
126 AllRules().prune(rule);
127 delete (rule);
128 break;
129 }
130 }
131 }
132
133 void
134 Adaptation::Config::clear()
135 {
136 debugs(93, 3, HERE << "rules: " << AllRules().size() << ", groups: " <<
137 AllGroups().size() << ", services: " << serviceConfigs.size());
138 typedef ServiceConfigs::const_iterator SCI;
139 const ServiceConfigs& configs = serviceConfigs;
140 for (SCI cfg = configs.begin(); cfg != configs.end(); ++cfg)
141 removeService((*cfg)->key);
142 serviceConfigs.clear();
143 debugs(93, 3, HERE << "rules: " << AllRules().size() << ", groups: " <<
144 AllGroups().size() << ", services: " << serviceConfigs.size());
145 }
146
147 void
148 Adaptation::Config::parseService()
149 {
150 ServiceConfigPointer cfg = newServiceConfig();
151 if (!cfg->parse()) {
152 fatalf("%s:%d: malformed adaptation service configuration",
153 cfg_filename, config_lineno);
154 }
155 serviceConfigs.push_back(cfg);
156 }
157
158 void
159 Adaptation::Config::freeService()
160 {
161 FreeAccess();
162 FreeServiceGroups();
163
164 DetachServices();
165
166 serviceConfigs.clear();
167 }
168
169 void
170 Adaptation::Config::dumpService(StoreEntry *entry, const char *name) const
171 {
172 typedef Services::iterator SCI;
173 for (SCI i = AllServices().begin(); i != AllServices().end(); ++i) {
174 const ServiceConfig &cfg = (*i)->cfg();
175 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "_%s %s %d " SQUIDSTRINGPH "\n",
176 name,
177 SQUIDSTRINGPRINT(cfg.key),
178 cfg.methodStr(), cfg.vectPointStr(), cfg.bypass,
179 SQUIDSTRINGPRINT(cfg.uri));
180 }
181 }
182
183 bool
184 Adaptation::Config::finalize()
185 {
186 if (!onoff) {
187 clear();
188 return false;
189 }
190
191 // create service reps from service configs
192 int created = 0;
193
194 typedef ServiceConfigs::const_iterator VISCI;
195 const ServiceConfigs &configs = serviceConfigs;
196 for (VISCI i = configs.begin(); i != configs.end(); ++i) {
197 const ServiceConfigPointer cfg = *i;
198 if (FindService(cfg->key) != NULL) {
199 debugs(93, DBG_CRITICAL, "ERROR: Duplicate adaptation service name: " <<
200 cfg->key);
201 continue; // TODO: make fatal
202 }
203 ServicePointer s = createService(cfg);
204 if (s != NULL) {
205 AllServices().push_back(s);
206 ++created;
207 }
208 }
209
210 debugs(93,3, HERE << "Created " << created << " adaptation services");
211
212 // services remember their configs; we do not have to
213 serviceConfigs.clear();
214 return true;
215 }
216
217 // poor man for_each
218 template <class Collection>
219 static void
220 FinalizeEach(Collection &collection, const char *label)
221 {
222 typedef typename Collection::iterator CI;
223 for (CI i = collection.begin(); i != collection.end(); ++i)
224 (*i)->finalize();
225
226 debugs(93,2, HERE << "Initialized " << collection.size() << ' ' << label);
227 }
228
229 void
230 Adaptation::Config::Finalize(bool enabled)
231 {
232 Enabled = enabled;
233 debugs(93, DBG_IMPORTANT, "Adaptation support is " << (Enabled ? "on" : "off."));
234
235 FinalizeEach(AllServices(), "message adaptation services");
236 FinalizeEach(AllGroups(), "message adaptation service groups");
237 FinalizeEach(AllRules(), "message adaptation access rules");
238 }
239
240 void
241 Adaptation::Config::ParseServiceSet()
242 {
243 Adaptation::Config::ParseServiceGroup(new ServiceSet);
244 }
245
246 void
247 Adaptation::Config::ParseServiceChain()
248 {
249 Adaptation::Config::ParseServiceGroup(new ServiceChain);
250 }
251
252 void
253 Adaptation::Config::ParseServiceGroup(ServiceGroupPointer g)
254 {
255 assert(g != NULL);
256 g->parse();
257 AllGroups().push_back(g);
258 }
259
260 void
261 Adaptation::Config::FreeServiceGroups()
262 {
263 while (!AllGroups().empty()) {
264 // groups are refcounted so we do not explicitly delete them
265 AllGroups().pop_back();
266 }
267 }
268
269 void
270 Adaptation::Config::DumpServiceGroups(StoreEntry *entry, const char *name)
271 {
272 typedef Groups::iterator GI;
273 for (GI i = AllGroups().begin(); i != AllGroups().end(); ++i)
274 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "\n", name, SQUIDSTRINGPRINT((*i)->id));
275 }
276
277 void
278 Adaptation::Config::ParseAccess(ConfigParser &parser)
279 {
280 String groupId = ConfigParser::NextToken();
281 AccessRule *r;
282 if (!(r=FindRuleByGroupId(groupId))) {
283 r = new AccessRule(groupId);
284 AllRules().push_back(r);
285 }
286 r->parse(parser);
287 }
288
289 void
290 Adaptation::Config::FreeAccess()
291 {
292 while (!AllRules().empty()) {
293 delete AllRules().back();
294 AllRules().pop_back();
295 }
296 }
297
298 void
299 Adaptation::Config::DumpAccess(StoreEntry *entry, const char *name)
300 {
301 LOCAL_ARRAY(char, nom, 64);
302
303 typedef AccessRules::iterator CI;
304 for (CI i = AllRules().begin(); i != AllRules().end(); ++i) {
305 snprintf(nom, 64, "%s " SQUIDSTRINGPH, name, SQUIDSTRINGPRINT((*i)->groupId));
306 dump_acl_access(entry, nom, (*i)->acl);
307 }
308 }
309
310 Adaptation::Config::Config() :
311 onoff(0), service_failure_limit(0), oldest_service_failure(0),
312 service_revival_delay(0)
313 {}
314
315 // XXX: this is called for ICAP and eCAP configs, but deals mostly
316 // with global arrays shared by those individual configs
317 Adaptation::Config::~Config()
318 {
319 freeService();
320 }