]> git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/Config.cc
Merged from trunk (r12813).
[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);
70
71 Adaptation::ServiceConfig*
72 Adaptation::Config::newServiceConfig() const
73 {
74 return new ServiceConfig();
75 }
76
77 void
78 Adaptation::Config::removeService(const String& service)
79 {
80 removeRule(service);
81 const Groups& groups = AllGroups();
82 for (unsigned int i = 0; i < groups.size(); ) {
83 const ServiceGroupPointer group = groups[i];
84 const ServiceGroup::Store& services = group->services;
85 typedef ServiceGroup::Store::const_iterator SGSI;
86 for (SGSI it = services.begin(); it != services.end(); ++it) {
87 if (*it == service) {
88 group->removedServices.push_back(service);
89 group->services.prune(service);
90 debugs(93, 5, HERE << "adaptation service " << service <<
91 " removed from group " << group->id);
92 break;
93 }
94 }
95 if (services.empty()) {
96 removeRule(group->id);
97 AllGroups().prune(group);
98 } else {
99 ++i;
100 }
101 }
102 }
103
104 void
105 Adaptation::Config::removeRule(const String& id)
106 {
107 typedef AccessRules::const_iterator ARI;
108 const AccessRules& rules = AllRules();
109 for (ARI it = rules.begin(); it != rules.end(); ++it) {
110 AccessRule* rule = *it;
111 if (rule->groupId == id) {
112 debugs(93, 5, HERE << "removing access rules for:" << id);
113 AllRules().prune(rule);
114 delete (rule);
115 break;
116 }
117 }
118 }
119
120 void
121 Adaptation::Config::clear()
122 {
123 debugs(93, 3, HERE << "rules: " << AllRules().size() << ", groups: " <<
124 AllGroups().size() << ", services: " << serviceConfigs.size());
125 typedef ServiceConfigs::const_iterator SCI;
126 const ServiceConfigs& configs = serviceConfigs;
127 for (SCI cfg = configs.begin(); cfg != configs.end(); ++cfg)
128 removeService((*cfg)->key);
129 serviceConfigs.clean();
130 debugs(93, 3, HERE << "rules: " << AllRules().size() << ", groups: " <<
131 AllGroups().size() << ", services: " << serviceConfigs.size());
132 }
133
134 void
135 Adaptation::Config::parseService()
136 {
137 ServiceConfigPointer cfg = newServiceConfig();
138 if (!cfg->parse()) {
139 fatalf("%s:%d: malformed adaptation service configuration",
140 cfg_filename, config_lineno);
141 }
142 serviceConfigs.push_back(cfg);
143 }
144
145 void
146 Adaptation::Config::freeService()
147 {
148 FreeAccess();
149 FreeServiceGroups();
150
151 DetachServices();
152
153 serviceConfigs.clean();
154 }
155
156 void
157 Adaptation::Config::dumpService(StoreEntry *entry, const char *name) const
158 {
159 typedef Services::iterator SCI;
160 for (SCI i = AllServices().begin(); i != AllServices().end(); ++i) {
161 const ServiceConfig &cfg = (*i)->cfg();
162 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "_%s %s %d " SQUIDSTRINGPH "\n",
163 name,
164 SQUIDSTRINGPRINT(cfg.key),
165 cfg.methodStr(), cfg.vectPointStr(), cfg.bypass,
166 SQUIDSTRINGPRINT(cfg.uri));
167 }
168 }
169
170 bool
171 Adaptation::Config::finalize()
172 {
173 if (!onoff) {
174 clear();
175 return false;
176 }
177
178 // create service reps from service configs
179 int created = 0;
180
181 typedef ServiceConfigs::const_iterator VISCI;
182 const ServiceConfigs &configs = serviceConfigs;
183 for (VISCI i = configs.begin(); i != configs.end(); ++i) {
184 const ServiceConfigPointer cfg = *i;
185 if (FindService(cfg->key) != NULL) {
186 debugs(93, DBG_CRITICAL, "ERROR: Duplicate adaptation service name: " <<
187 cfg->key);
188 continue; // TODO: make fatal
189 }
190 ServicePointer s = createService(cfg);
191 if (s != NULL) {
192 AllServices().push_back(s);
193 ++created;
194 }
195 }
196
197 debugs(93,3, HERE << "Created " << created << " adaptation services");
198
199 // services remember their configs; we do not have to
200 serviceConfigs.clean();
201 return true;
202 }
203
204 // poor man for_each
205 template <class Collection>
206 static void
207 FinalizeEach(Collection &collection, const char *label)
208 {
209 typedef typename Collection::iterator CI;
210 for (CI i = collection.begin(); i != collection.end(); ++i)
211 (*i)->finalize();
212
213 debugs(93,2, HERE << "Initialized " << collection.size() << ' ' << label);
214 }
215
216 void
217 Adaptation::Config::Finalize(bool enabled)
218 {
219 Enabled = enabled;
220 debugs(93, DBG_IMPORTANT, "Adaptation support is " << (Enabled ? "on" : "off."));
221
222 FinalizeEach(AllServices(), "message adaptation services");
223 FinalizeEach(AllGroups(), "message adaptation service groups");
224 FinalizeEach(AllRules(), "message adaptation access rules");
225 }
226
227 void
228 Adaptation::Config::ParseServiceSet()
229 {
230 Adaptation::Config::ParseServiceGroup(new ServiceSet);
231 }
232
233 void
234 Adaptation::Config::ParseServiceChain()
235 {
236 Adaptation::Config::ParseServiceGroup(new ServiceChain);
237 }
238
239 void
240 Adaptation::Config::ParseServiceGroup(ServiceGroupPointer g)
241 {
242 assert(g != NULL);
243 g->parse();
244 AllGroups().push_back(g);
245 }
246
247 void
248 Adaptation::Config::FreeServiceGroups()
249 {
250 while (!AllGroups().empty()) {
251 // groups are refcounted so we do not explicitly delete them
252 AllGroups().pop_back();
253 }
254 }
255
256 void
257 Adaptation::Config::DumpServiceGroups(StoreEntry *entry, const char *name)
258 {
259 typedef Groups::iterator GI;
260 for (GI i = AllGroups().begin(); i != AllGroups().end(); ++i)
261 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "\n", name, SQUIDSTRINGPRINT((*i)->id));
262 }
263
264 void
265 Adaptation::Config::ParseAccess(ConfigParser &parser)
266 {
267 String groupId;
268 ConfigParser::ParseString(&groupId);
269 AccessRule *r;
270 if (!(r=FindRuleByGroupId(groupId))) {
271 r = new AccessRule(groupId);
272 AllRules().push_back(r);
273 }
274 r->parse(parser);
275 }
276
277 void
278 Adaptation::Config::FreeAccess()
279 {
280 while (!AllRules().empty()) {
281 delete AllRules().back();
282 AllRules().pop_back();
283 }
284 }
285
286 void
287 Adaptation::Config::DumpAccess(StoreEntry *entry, const char *name)
288 {
289 LOCAL_ARRAY(char, nom, 64);
290
291 typedef AccessRules::iterator CI;
292 for (CI i = AllRules().begin(); i != AllRules().end(); ++i) {
293 snprintf(nom, 64, "%s " SQUIDSTRINGPH, name, SQUIDSTRINGPRINT((*i)->groupId));
294 dump_acl_access(entry, nom, (*i)->acl);
295 }
296 }
297
298 Adaptation::Config::Config() :
299 onoff(0), service_failure_limit(0), oldest_service_failure(0),
300 service_revival_delay(0)
301 {}
302
303 // XXX: this is called for ICAP and eCAP configs, but deals mostly
304 // with global arrays shared by those individual configs
305 Adaptation::Config::~Config()
306 {
307 freeService();
308 }